Skip to content

Commit 976248e

Browse files
author
Anton
committed
feat: implement v1.1.1 (Background Service, CI/CD, and Console Toggle)
1 parent c0fd675 commit 976248e

100 files changed

Lines changed: 444 additions & 98 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yml

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,8 @@ on:
66
- 'v*'
77

88
jobs:
9-
release:
9+
build-windows:
1010
runs-on: windows-latest
11-
permissions:
12-
contents: write
13-
1411
steps:
1512
- name: Checkout code
1613
uses: actions/checkout@v4
@@ -30,28 +27,84 @@ jobs:
3027
- name: Zip Release
3128
shell: pwsh
3229
run: |
33-
# The publish directory contains the .exe and Assets/ folder
3430
Compress-Archive -Path publish/* -DestinationPath clock.zip
3531
32+
- name: Upload Windows Artifact
33+
uses: actions/upload-artifact@v4
34+
with:
35+
name: windows-release
36+
path: clock.zip
37+
38+
build-android:
39+
runs-on: ubuntu-latest
40+
steps:
41+
- name: Checkout code
42+
uses: actions/checkout@v4
43+
44+
- name: set up JDK 17
45+
uses: actions/setup-java@v4
46+
with:
47+
java-version: '17'
48+
distribution: 'temurin'
49+
cache: gradle
50+
51+
- name: Grant execute permission for gradlew
52+
run: chmod +x clock-android/gradlew
53+
54+
- name: Build with Gradle
55+
run: cd clock-android && ./gradlew assembleRelease
56+
57+
- name: Upload APK
58+
uses: actions/upload-artifact@v4
59+
with:
60+
name: android-release
61+
path: clock-android/app/build/outputs/apk/release/app-release.apk
62+
63+
create-release:
64+
needs: [build-windows, build-android]
65+
runs-on: ubuntu-latest
66+
permissions:
67+
contents: write
68+
steps:
69+
- name: Download Windows Artifact
70+
uses: actions/download-artifact@v4
71+
with:
72+
name: windows-release
73+
74+
- name: Download Android Artifact
75+
uses: actions/download-artifact@v4
76+
with:
77+
name: android-release
78+
79+
- name: Rename APK
80+
run: mv app-release.apk clock.apk
81+
3682
- name: Create Release
3783
uses: softprops/action-gh-release@v2
3884
with:
39-
files: clock.zip
85+
files: |
86+
clock.zip
87+
clock.apk
4088
name: Release ${{ github.ref_name }}
4189
body: |
4290
## Clock v${{ github.ref_name }}
4391
44-
Automatic build by GitHub Actions.
92+
Automatic build by GitHub Actions for multiple platforms.
4593
46-
### Installation
47-
1. Download `clock.zip` below.
94+
### Windows Installation
95+
1. Download `clock.zip`.
4896
2. Extract to a folder.
4997
3. **Important**: Add your notification sound as `Assets/notify.wav`.
5098
4. Run `clock.exe`.
5199
100+
### Android Installation
101+
1. Download `clock.apk`.
102+
2. Install on your Android device.
103+
3. Uses system default notification sounds.
104+
52105
---
53106
*Built with Google Gemini & GitHub Actions*
54107
draft: false
55108
prerelease: false
56109
env:
57-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
110+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

App.xaml.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System.Runtime.InteropServices;
22
using System.Windows;
33
using clock.Services;
44
using clock.ViewModels;
@@ -10,6 +10,10 @@ namespace clock
1010
{
1111
public partial class App : Application
1212
{
13+
[DllImport("kernel32.dll", SetLastError = true)]
14+
[return: MarshalAs(UnmanagedType.Bool)]
15+
static extern bool AllocConsole();
16+
1317
private SyncServerService? _syncServer;
1418
private MdnsService? _mdns;
1519

@@ -23,12 +27,19 @@ protected override void OnStartup(StartupEventArgs e)
2327
{
2428
base.OnStartup(e);
2529

30+
var settings = AppSettings.Load();
31+
if (settings.ShowConsole)
32+
{
33+
AllocConsole();
34+
Console.WriteLine("[System] Console allocated by user preference.");
35+
}
36+
2637
var settingsService = new SettingsService();
2738
var timer = new WpfTimer();
2839
var audioService = new WpfAudioService();
2940

3041
// 建立初始引擎
31-
var initialEngine = new PomodoroEngine(AppSettings.Load(), timer);
42+
var initialEngine = new PomodoroEngine(settings, timer);
3243
_syncServer = new SyncServerService(initialEngine);
3344

3445
var uiService = new WpfUIService(async () => {

README.md

Lines changed: 15 additions & 10 deletions

Tests/clock.IntegrationTests/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ static void Main(string[] args)
1818
Test_TogglePause();
1919
Test_Settings();
2020
Test_StartupService();
21+
SettingsTests.RunTests();
2122
EngineTickingTests.RunTests();
2223
StateSyncTests.RunTests();
2324
Console.WriteLine("All tests passed!");
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using clock.Models;
2+
using System;
3+
using System.IO;
4+
5+
namespace clock.IntegrationTests
6+
{
7+
public class SettingsTests
8+
{
9+
public static void RunTests()
10+
{
11+
Test_AppSettings_SaveAndLoadShowConsole();
12+
}
13+
14+
static void Test_AppSettings_SaveAndLoadShowConsole()
15+
{
16+
// Arrange
17+
var settings = new AppSettings();
18+
settings.ShowConsole = false;
19+
20+
// Act
21+
settings.Save();
22+
var loaded = AppSettings.Load();
23+
24+
// Assert
25+
if (loaded.ShowConsole != false)
26+
{
27+
throw new Exception("AppSettings failed to save/load ShowConsole property.");
28+
}
29+
30+
// Cleanup: Reset
31+
loaded.ShowConsole = true;
32+
loaded.Save();
33+
34+
Console.WriteLine("Test_AppSettings_SaveAndLoadShowConsole Passed");
35+
}
36+
}
37+
}

Views/SettingsWindow.xaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@
116116
<TextBlock Text="Notification Volume"/>
117117
<Slider x:Name="VolumeSlider" Minimum="0" Maximum="100" Margin="0,0,0,10"/>
118118

119-
<CheckBox x:Name="StartupCheck" Content="Run at Startup" Margin="0,0,0,20" FontWeight="Bold"/>
119+
<CheckBox x:Name="StartupCheck" Content="Run at Startup" Margin="0,0,0,10" FontWeight="Bold"/>
120+
121+
<CheckBox x:Name="ConsoleCheck" Content="Show Developer Console (CMD)" Margin="0,0,0,20" FontWeight="Bold"/>
120122

121123
<Button Content="Save &amp; Close" Click="Save_Click" Height="40" Background="#007ACC" Foreground="White" FontWeight="Bold"/>
122124
</StackPanel>

Views/SettingsWindow.xaml.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public SettingsWindow(AppSettings settings)
2828
// 啟動時檢查實際檔案狀態,讓介面更精準
2929
_settings.IsStartupEnabled = StartupService.IsStartupEnabled();
3030
StartupCheck.IsChecked = _settings.IsStartupEnabled;
31+
ConsoleCheck.IsChecked = _settings.ShowConsole;
3132

3233
// 初始化字型選單
3334
FontFamilyCombo.ItemsSource = Fonts.SystemFontFamilies.OrderBy(f => f.Source);
@@ -60,6 +61,8 @@ public SettingsWindow(AppSettings settings)
6061
VolumeSlider.ValueChanged += (s, e) => _settings.Volume = VolumeSlider.Value;
6162
StartupCheck.Checked += (s, e) => _settings.IsStartupEnabled = true;
6263
StartupCheck.Unchecked += (s, e) => _settings.IsStartupEnabled = false;
64+
ConsoleCheck.Checked += (s, e) => _settings.ShowConsole = true;
65+
ConsoleCheck.Unchecked += (s, e) => _settings.ShowConsole = false;
6366
}
6467

6568
private void InitializeColorPicker(WrapPanel panel, TextBox box, Border preview, Action<string> updateAction, string initialValue, bool isText = false)
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
2.78 KB
Binary file not shown.

0 commit comments

Comments
 (0)