Explorar o código

some vibecoded changes

faqmoroz hai 1 semana
pai
achega
96988f86b9

+ 53 - 14
Minolta Remote/AppShell.xaml

@@ -5,24 +5,63 @@
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     xmlns:local="clr-namespace:Minolta_Remote"
     Shell.FlyoutBehavior="Disabled"
-    Title="Minolta_Remote">
-    <Tab Title="SImple">
-    <ShellContent
-        Title="Home"
-        ContentTemplate="{DataTemplate local:MainPage}"
-        Route="MainPage" />
+    Title="Minolta Remote"
+    Shell.NavBarIsVisible="True"
+    Shell.TabBarBackgroundColor="#121212"
+    Shell.TabBarForegroundColor="#FFFFFF"
+    Shell.TabBarTitleColor="#FFFFFF"
+    Shell.TabBarDisabledColor="#666666">
+
+    <Shell.Resources>
+        <!-- Shared camera logic instance -->
+        <local:CameraLogic x:Key="CameraLogic" />
+
+        <!-- Tab text styling -->
+        <Style TargetType="TabBar">
+            <Setter Property="Shell.TabBarTitleColor" Value="#FFFFFF" />
+            <Setter Property="Shell.TabBarForegroundColor" Value="#FFFFFF" />
+            <Setter Property="Shell.TabBarBackgroundColor" Value="#121212" />
+        </Style>
+
+        <!-- Slightly larger, bold tab titles -->
+        <Style TargetType="Tab">
+            <Setter Property="Shell.TabBarForegroundColor" Value="#FFFFFF" />
+            <Setter Property="Shell.TabBarTitleColor" Value="#FFFFFF" />
+            <Setter Property="Shell.TitleView">
+                <Setter.Value>
+                    <Grid Padding="0,6">
+                        <Label
+                            Text="{Binding Title, Source={RelativeSource AncestorType={x:Type Tab}}}"
+                            FontAttributes="Bold"
+                            FontSize="14"
+                            TextColor="#FFFFFF"
+                            HorizontalTextAlignment="Center"
+                            VerticalTextAlignment="Center" />
+                    </Grid>
+                </Setter.Value>
+            </Setter>
+        </Style>
+    </Shell.Resources>
+
+    <Tab Title="Auto Mode">
+        <ShellContent
+            Title="Auto Mode"
+            ContentTemplate="{DataTemplate local:MainPage}"
+            Route="AutoMode" />
     </Tab>
-    <Tab Title="Pro">
+
+    <Tab Title="Bulb Mode">
         <ShellContent
-     Title="Home"
-     ContentTemplate="{DataTemplate local:ProTab}"
-     Route="MainPage" />
+            Title="Bulb Mode"
+            ContentTemplate="{DataTemplate local:ProTab}"
+            Route="BulbMode" />
     </Tab>
-    <Tab Title="Timelapse">
+
+    <Tab Title="TimeLapse Mode">
         <ShellContent
- Title="Home"
- ContentTemplate="{DataTemplate local:TimelapsePage}"
- Route="MainPage" />
+            Title="TimeLapse Mode"
+            ContentTemplate="{DataTemplate local:TimelapsePage}"
+            Route="TimeLapseMode" />
     </Tab>
 
 </Shell>

+ 1 - 1
Minolta Remote/AppShell.xaml.cs

@@ -1,4 +1,4 @@
-namespace Minolta_Remote
+namespace Minolta_Remote
 {
     public partial class AppShell : Shell
     {

+ 32 - 0
Minolta Remote/BasePage.cs

@@ -0,0 +1,32 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Minolta_Remote;
+
+public class BasePage : ContentPage
+{
+    protected Task RunWithButtonDisabled(Button button, Func<Task> action)
+    {
+        if (button == null || action == null)
+            return Task.CompletedTask;
+
+        if (!button.IsEnabled)
+            return Task.CompletedTask;
+
+        async Task Wrapper()
+        {
+            button.IsEnabled = false;
+            try
+            {
+                await action();
+            }
+            finally
+            {
+                button.IsEnabled = true;
+            }
+        }
+
+        return Wrapper();
+    }
+}
+

+ 70 - 0
Minolta Remote/BusinessLogic.cs

@@ -0,0 +1,70 @@
+using System.Threading.Tasks;
+using Minolta_Remote.Services;
+
+namespace Minolta_Remote;
+
+public interface IMainPageLogic
+{
+    Task FocusAsync();
+    Task TakePhotoAsync();
+    Task ResetAsync();
+}
+
+public interface IProTabLogic
+{
+    Task TakePhotoAsync(int shootTimeMs, int selfTimerMs, bool isPrefocusEnabled);
+    Task ResetAsync();
+}
+
+public interface ITimelapseLogic
+{
+    Task StartTimelapseAsync(int count, int delayMs, int? shootTimeMs);
+}
+
+/// <summary>
+/// Central camera logic that implements interfaces for all modes.
+/// </summary>
+public class CameraLogic : IMainPageLogic, IProTabLogic, ITimelapseLogic
+{
+    private readonly IEspClient _espClient;
+
+    public CameraLogic()
+    {
+        var factory = new EspClientFactory();
+        _espClient = factory.CreateEspClient();
+    }
+
+    // IMainPageLogic
+    public Task FocusAsync() => _espClient.FocusAsync();
+
+    public Task TakePhotoAsync() => _espClient.TakePhotoAsync();
+
+    public Task ResetAsync() => _espClient.ResetAsync();
+
+    // IProTabLogic
+    public async Task TakePhotoAsync(int shootTimeMs, int selfTimerMs, bool isPrefocusEnabled)
+    {
+        if (selfTimerMs > 0)
+        {
+            System.Threading.Thread.Sleep(selfTimerMs);
+            await _espClient.FocusAsync();
+            System.Threading.Thread.Sleep(1000);
+            await _espClient.TakePhotoAsync(shootTimeMs);
+        }
+        else
+        {
+            if (isPrefocusEnabled)
+            {
+                await _espClient.FocusAsync();
+                System.Threading.Thread.Sleep(1000);
+            }
+
+            await _espClient.TakePhotoAsync(shootTimeMs);
+        }
+    }
+
+    // ITimelapseLogic
+    public Task StartTimelapseAsync(int count, int delayMs, int? shootTimeMs)
+        => _espClient.MultipleAsync(count, delayMs, shootTimeMs);
+}
+

+ 56 - 12
Minolta Remote/MainPage.xaml

@@ -1,14 +1,58 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
+<?xml version="1.0" encoding="utf-8" ?>
+<base:BasePage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
-             x:Class="Minolta_Remote.MainPage">
-   
-    <Grid>
-        <Grid.RowDefinitions>       
-            <RowDefinition />
-            <RowDefinition/>
-        </Grid.RowDefinitions>   
-        <Button x:Name="Prefocus" Text="Prefocus" Grid.Row="0" HorizontalOptions="Center" VerticalOptions="Center" Clicked="Focus_Button_Clicked"/>
-        <Button x:Name="TakePhoto" Text="TakePhoto" Grid.Row="1" HorizontalOptions="Center" VerticalOptions="Center" Clicked="TakePhoto_Button_Clicked"/>
+             x:Class="Minolta_Remote.MainPage"
+             xmlns:base="clr-namespace:Minolta_Remote"
+             BackgroundColor="#121212">
+
+    <ContentPage.Resources>
+        <Style TargetType="Label">
+            <Setter Property="TextColor" Value="White" />
+            <Setter Property="FontSize" Value="18" />
+        </Style>
+        <Style TargetType="Button">
+            <Setter Property="BackgroundColor" Value="#1E88E5" />
+            <Setter Property="TextColor" Value="White" />
+            <Setter Property="CornerRadius" Value="24" />
+            <Setter Property="HeightRequest" Value="48" />
+            <Setter Property="WidthRequest" Value="220" />
+            <Setter Property="Margin" Value="0,8" />
+        </Style>
+    </ContentPage.Resources>
+
+    <Grid Padding="24">
+        <Grid.RowDefinitions>
+            <RowDefinition Height="Auto" />
+            <RowDefinition Height="*" />
+            <RowDefinition Height="Auto" />
+            <RowDefinition Height="Auto" />
+        </Grid.RowDefinitions>
+
+        <Label
+            Grid.Row="0"
+            Text="Auto Mode"
+            FontAttributes="Bold"
+            FontSize="24"
+            HorizontalOptions="Center"
+            Margin="0,0,0,16" />
+
+        <VerticalStackLayout
+            Grid.Row="1"
+            Spacing="12"
+            VerticalOptions="CenterAndExpand"
+            HorizontalOptions="Center">
+            <Button
+                x:Name="Prefocus"
+                Text="Prefocus"
+                Clicked="Focus_Button_Clicked" />
+            <Button
+                x:Name="TakePhoto"
+                Text="Take Photo"
+                Clicked="TakePhoto_Button_Clicked" />
+            <Button
+                x:Name="ResetButon"
+                Text="Reset camera focus"
+                Clicked="ResetButon_Clicked" />
+        </VerticalStackLayout>
     </Grid>
-</ContentPage>
+</base:BasePage>

+ 11 - 13
Minolta Remote/MainPage.xaml.cs

@@ -1,30 +1,28 @@
-using Minolta_Remote.Services;
-
 namespace Minolta_Remote
 {
-    public partial class MainPage : ContentPage
+    public partial class MainPage : BasePage
     {
-        private readonly IEspClient espClient;
-        
+        private IMainPageLogic Logic =>
+            (IMainPageLogic)((AppShell)Application.Current.MainPage).Resources["CameraLogic"];
+
         public MainPage()
         {
             InitializeComponent();
-            var factory = new EspClientFactory();
-            espClient = factory.CreateEspClient();
         }
 
         private async void Focus_Button_Clicked(object sender, EventArgs e)
         {
-            this.Prefocus.IsEnabled = false;
-            var result = await espClient.FocusAsync();
-            this.Prefocus.IsEnabled = true;
+            await RunWithButtonDisabled(Prefocus, () => Logic.FocusAsync());
         }
 
         private async void TakePhoto_Button_Clicked(object sender, EventArgs e)
         {
-            this.TakePhoto.IsEnabled = false;
-            var result = await espClient.TakePhotoAsync();
-            this.TakePhoto.IsEnabled = true;
+            await RunWithButtonDisabled(TakePhoto, () => Logic.TakePhotoAsync());
+        }
+
+        private async void ResetButon_Clicked(object sender, EventArgs e)
+        {
+            await RunWithButtonDisabled(ResetButon, () => Logic.ResetAsync());
         }
     }
 

+ 56 - 20
Minolta Remote/ProTab.xaml

@@ -1,26 +1,62 @@
 <?xml version="1.0" encoding="utf-8" ?>
-<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
+<base:BasePage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="Minolta_Remote.ProTab"
-             Title="ProTab">
-    <VerticalStackLayout Margin="30">
-        <HorizontalStackLayout Margin="15" Spacing="10">
-            <Label VerticalTextAlignment="Center">Выдержка милисекунд</Label>
-            <Entry x:Name="ShootTime" Keyboard="Numeric"/>
-        </HorizontalStackLayout>
-        <HorizontalStackLayout Margin="15" Spacing="10">
-            <Label VerticalTextAlignment="Center">Селфитаймер, милисекунд</Label>
-            <Entry x:Name="SelfiTimer" Keyboard="Numeric"/>
-        </HorizontalStackLayout>
-        <HorizontalStackLayout Margin="15" Spacing="10">
-            <Label VerticalTextAlignment="Center">Предфокусировка</Label>
-            <Switch x:Name="Prefocus"/>
-        </HorizontalStackLayout>
-        <HorizontalStackLayout Margin="15" Spacing="10">
+               xmlns:base="clr-namespace:Minolta_Remote"
+             Title="ProTab"
+             BackgroundColor="#121212">
+
+    <ContentPage.Resources>
+        <Style TargetType="Label">
+            <Setter Property="TextColor" Value="White" />
+            <Setter Property="FontSize" Value="16" />
+        </Style>
+        <Style TargetType="Entry">
+            <Setter Property="TextColor" Value="White" />
+            <Setter Property="BackgroundColor" Value="#1E1E1E" />
+            <Setter Property="Margin" Value="0,4" />
+        </Style>
+        <Style TargetType="Button">
+            <Setter Property="BackgroundColor" Value="#1E88E5" />
+            <Setter Property="TextColor" Value="White" />
+            <Setter Property="CornerRadius" Value="24" />
+            <Setter Property="HeightRequest" Value="48" />
+            <Setter Property="Margin" Value="0,8" />
+        </Style>
+    </ContentPage.Resources>
+
+    <VerticalStackLayout Padding="24" Spacing="16">
+        <Label
+            Text="Bulb Mode"
+            FontAttributes="Bold"
+            FontSize="24"
+            HorizontalOptions="Center"
+            Margin="0,0,0,8" />
+
+        <Frame
+            Padding="16"
+            CornerRadius="12"
+            BackgroundColor="#1E1E1E"
+            HasShadow="False">
+            <VerticalStackLayout Spacing="12">
+                <HorizontalStackLayout Spacing="10">
+                    <Label VerticalTextAlignment="Center">Shutter speed, ms</Label>
+                    <Entry x:Name="ShootTime" Keyboard="Numeric" HorizontalOptions="FillAndExpand"/>
+                </HorizontalStackLayout>
+                <HorizontalStackLayout Spacing="10">
+                    <Label VerticalTextAlignment="Center">Self-timer, ms</Label>
+                    <Entry x:Name="SelfiTimer" Keyboard="Numeric" HorizontalOptions="FillAndExpand"/>
+                </HorizontalStackLayout>
+                <HorizontalStackLayout Spacing="10">
+                    <Label VerticalTextAlignment="Center">Prefocus</Label>
+                    <Switch x:Name="Prefocus" HorizontalOptions="EndAndExpand"/>
+                </HorizontalStackLayout>
+            </VerticalStackLayout>
+        </Frame>
+
+        <VerticalStackLayout Spacing="8">
             <Button Text="Take Photo" x:Name="ShootButon" Clicked="ShootButon_Clicked"/>
-        </HorizontalStackLayout>
-        <HorizontalStackLayout Margin="15" Spacing="10">
             <Button Text="Reset camera focus" x:Name="ResetButon" Clicked="ResetButon_Clicked"/>
-        </HorizontalStackLayout>
+        </VerticalStackLayout>
     </VerticalStackLayout>
-</ContentPage>
+</base:BasePage>

+ 13 - 30
Minolta Remote/ProTab.xaml.cs

@@ -1,16 +1,13 @@
-using Minolta_Remote.Services;
-
 namespace Minolta_Remote;
 
-public partial class ProTab : ContentPage
+public partial class ProTab : BasePage
 {
-    private readonly IEspClient espClient;
+    private IProTabLogic Logic =>
+        (IProTabLogic)((AppShell)Application.Current.MainPage).Resources["CameraLogic"];
     
     public ProTab()
     {
         InitializeComponent();
-        var factory = new EspClientFactory();
-        espClient = factory.CreateEspClient();
         ShootTime.Text = "1000";
         SelfiTimer.Text = "0";
         Prefocus.IsToggled = true;
@@ -19,37 +16,23 @@ public partial class ProTab : ContentPage
 
     private async void ShootButon_Clicked(object sender, EventArgs e)
     {
-        ShootButon.IsEnabled = false;
-        try {
-            int shootTime = int.Parse(ShootTime.Text);
-            int selfiTime = int.Parse(SelfiTimer.Text);
-            bool isPrefocusEnabled = Prefocus.IsToggled;
-            if (selfiTime>0)
+        await RunWithButtonDisabled(ShootButon, async () =>
+        {
+            try
             {
-                System.Threading.Thread.Sleep(selfiTime);
-                await espClient.FocusAsync();
-                System.Threading.Thread.Sleep(1000);
-                await espClient.TakePhotoAsync(shootTime);
+                int shootTime = int.Parse(ShootTime.Text);
+                int selfiTime = int.Parse(SelfiTimer.Text);
+                bool isPrefocusEnabled = Prefocus.IsToggled;
+                await Logic.TakePhotoAsync(shootTime, selfiTime, isPrefocusEnabled);
             }
-            else
+            catch
             {
-                if (isPrefocusEnabled)
-                {
-                    await espClient.FocusAsync();
-                    System.Threading.Thread.Sleep(1000);
-                }
-                await espClient.TakePhotoAsync(shootTime);
             }
-        }
-        catch { }
-
-        ShootButon.IsEnabled = true;
+        });
     }
 
     private async void ResetButon_Clicked(object sender, EventArgs e)
     {
-        ResetButon.IsEnabled = false;
-        await espClient.ResetAsync();
-        ResetButon.IsEnabled = true;
+        await RunWithButtonDisabled(ResetButon, () => Logic.ResetAsync());
     }
 }

+ 55 - 19
Minolta Remote/TimelapsePage.xaml

@@ -1,23 +1,59 @@
 <?xml version="1.0" encoding="utf-8" ?>
-<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
+<base:BasePage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="Minolta_Remote.TimelapsePage"
-             Title="TimelapsePage">
-    <VerticalStackLayout Margin="30">
-        <HorizontalStackLayout Margin="15" Spacing="10">
-            <Label VerticalTextAlignment="Center">Выдержка милисекунд</Label>
-            <Entry x:Name="ShootTime" Keyboard="Numeric"/>
-        </HorizontalStackLayout>
-        <HorizontalStackLayout Margin="15" Spacing="10">
-            <Label VerticalTextAlignment="Center">Задержка между кадрами</Label>
-            <Entry x:Name="Delay" Keyboard="Numeric"/>
-        </HorizontalStackLayout>
-        <HorizontalStackLayout Margin="15" Spacing="10">
-            <Label VerticalTextAlignment="Center">Количество фото</Label>
-            <Entry x:Name="PhotoCount" Keyboard="Numeric"/>
-        </HorizontalStackLayout>
-        <HorizontalStackLayout Margin="15" Spacing="10">
-            <Button Text="Take Photo" x:Name="ShootButon" Clicked="ShootButon_Clicked"/>
-        </HorizontalStackLayout>
+               xmlns:base="clr-namespace:Minolta_Remote"
+             Title="TimelapsePage"
+             BackgroundColor="#121212">
+
+    <ContentPage.Resources>
+        <Style TargetType="Label">
+            <Setter Property="TextColor" Value="White" />
+            <Setter Property="FontSize" Value="16" />
+        </Style>
+        <Style TargetType="Entry">
+            <Setter Property="TextColor" Value="White" />
+            <Setter Property="BackgroundColor" Value="#1E1E1E" />
+            <Setter Property="Margin" Value="0,4" />
+        </Style>
+        <Style TargetType="Button">
+            <Setter Property="BackgroundColor" Value="#1E88E5" />
+            <Setter Property="TextColor" Value="White" />
+            <Setter Property="CornerRadius" Value="24" />
+            <Setter Property="HeightRequest" Value="48" />
+            <Setter Property="Margin" Value="0,8" />
+        </Style>
+    </ContentPage.Resources>
+
+    <VerticalStackLayout Padding="24" Spacing="16">
+        <Label
+            Text="TimeLapse Mode"
+            FontAttributes="Bold"
+            FontSize="24"
+            HorizontalOptions="Center"
+            Margin="0,0,0,8" />
+
+        <Frame
+            Padding="16"
+            CornerRadius="12"
+            BackgroundColor="#1E1E1E"
+            HasShadow="False">
+            <VerticalStackLayout Spacing="12">
+                <HorizontalStackLayout Spacing="10">
+                    <Label VerticalTextAlignment="Center">Shutter speed, ms</Label>
+                    <Entry x:Name="ShootTime" Keyboard="Numeric" HorizontalOptions="FillAndExpand"/>
+                </HorizontalStackLayout>
+                <HorizontalStackLayout Spacing="10">
+                    <Label VerticalTextAlignment="Center">Delay between shots, ms</Label>
+                    <Entry x:Name="Delay" Keyboard="Numeric" HorizontalOptions="FillAndExpand"/>
+                </HorizontalStackLayout>
+                <HorizontalStackLayout Spacing="10">
+                    <Label VerticalTextAlignment="Center">Number of photos</Label>
+                    <Entry x:Name="PhotoCount" Keyboard="Numeric" HorizontalOptions="FillAndExpand"/>
+                </HorizontalStackLayout>
+            </VerticalStackLayout>
+        </Frame>
+
+        <Button Text="Start timelapse" x:Name="ShootButon" Clicked="ShootButon_Clicked"/>
     </VerticalStackLayout>
-</ContentPage>
+</base:BasePage>

+ 19 - 19
Minolta Remote/TimelapsePage.xaml.cs

@@ -1,35 +1,35 @@
-using Minolta_Remote.Services;
-
 namespace Minolta_Remote;
 
-public partial class TimelapsePage : ContentPage
+public partial class TimelapsePage : BasePage
 {
-    private readonly IEspClient espClient;
+    private ITimelapseLogic Logic =>
+        (ITimelapseLogic)((AppShell)Application.Current.MainPage).Resources["CameraLogic"];
     
     public TimelapsePage()
     {
         InitializeComponent();
-        var factory = new EspClientFactory();
-        espClient = factory.CreateEspClient();
         PhotoCount.Text = "1";
         Delay.Text = "1";
     }
 
     private async void ShootButon_Clicked(object sender, EventArgs e)
     {
-        ShootButon.IsEnabled = false;
-        int? shootTime = null;
-        int count = 1;
-        int delay = 0;
-        try
+        await RunWithButtonDisabled(ShootButon, async () =>
         {
-            count = int.Parse(PhotoCount.Text);
-            delay = int.Parse(Delay.Text);
-            if (!String.IsNullOrEmpty(ShootTime.Text))
-                shootTime = int.Parse(ShootTime.Text);
-        }
-        catch { }
-        await espClient.MultipleAsync(count, delay, shootTime);
-        ShootButon.IsEnabled = true;
+            int? shootTime = null;
+            int count = 1;
+            int delay = 0;
+            try
+            {
+                count = int.Parse(PhotoCount.Text);
+                delay = int.Parse(Delay.Text);
+                if (!String.IsNullOrEmpty(ShootTime.Text))
+                    shootTime = int.Parse(ShootTime.Text);
+            }
+            catch
+            {
+            }
+            await Logic.StartTimelapseAsync(count, delay, shootTime);
+        });
     }
 }