Skip to content

Commit 581cf06

Browse files
jkoenig134nicole-ebmergify[bot]
authored
Add windows support (#392)
* chore: add windows platform * chore: add windows * fiix: not request permissions on windows * feat: handle windows notifications * chore: add windows pipeline * fix: update windows icon * chore: simplify stuff * chore: better dummy values * fix: remove app id * ci: fix build * chore: windows path * feat: win notifications support * feat: app_links support * fix: add scrollcontrollers * fix: app links * fix: better check * chore: remove checks * feat: update msix settings * feat: auto msix building * fix: re-add android and ios to metadata * chore: remove todo * feat: use 512 icon * feat: specify languages * chore: pin countries * chore: bump runtime * fix: simplify config access * fix: get runtime config * chore: switch logger * fix: correctly handle runtime error * chore: remove unused code * chore: melos bootstrap * chore: rm lockfile * ci: only build windows maually --------- Co-authored-by: Nicole Ebken <[email protected]> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 41ac8d8 commit 581cf06

34 files changed

+1448
-20
lines changed

apps/enmeshed/.metadata

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# This file should be version controlled and should not be manually edited.
55

66
version:
7-
revision: "78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9"
7+
revision: "17025dd88227cd9532c33fa78f5250d548d87e9a"
88
channel: "stable"
99

1010
project_type: app
@@ -13,14 +13,17 @@ project_type: app
1313
migration:
1414
platforms:
1515
- platform: root
16-
create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
17-
base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
16+
create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
17+
base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
1818
- platform: android
19-
create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
20-
base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
19+
create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
20+
base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
2121
- platform: ios
22-
create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
23-
base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
22+
create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
23+
base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
24+
- platform: windows
25+
create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
26+
base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
2427

2528
# User provided section
2629

apps/enmeshed/assets/icon-512.png

19.3 KB
Loading

apps/enmeshed/lib/account/contacts/contact_detail_screen.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class ContactDetailScreen extends ContactSharedFilesWidget {
1818
}
1919

2020
class _ContactDetailScreenState extends State<ContactDetailScreen> with ContactSharedFilesMixin<ContactDetailScreen> {
21+
late final ScrollController _scrollController;
22+
2123
late final Session _session;
2224

2325
IdentityDVO? _contact;
@@ -33,6 +35,8 @@ class _ContactDetailScreenState extends State<ContactDetailScreen> with ContactS
3335
void initState() {
3436
super.initState();
3537

38+
_scrollController = ScrollController();
39+
3640
_session = GetIt.I.get<EnmeshedRuntime>().getSession(widget.accountId);
3741

3842
_reload();
@@ -50,6 +54,8 @@ class _ContactDetailScreenState extends State<ContactDetailScreen> with ContactS
5054

5155
@override
5256
void dispose() {
57+
_scrollController.dispose();
58+
5359
for (final subscription in _subscriptions) {
5460
subscription.cancel();
5561
}
@@ -77,8 +83,10 @@ class _ContactDetailScreenState extends State<ContactDetailScreen> with ContactS
7783
await loadSharedFiles(syncBefore: true);
7884
},
7985
child: Scrollbar(
86+
controller: _scrollController,
8087
thumbVisibility: true,
8188
child: ListView(
89+
controller: _scrollController,
8290
children: [
8391
ContactDetailHeader(contact: contact),
8492
ContactStatusInfoContainer(contact: contact),

apps/enmeshed/lib/account/home/home.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class HomeView extends StatefulWidget {
2020
}
2121

2222
class _HomeViewState extends State<HomeView> {
23+
late final ScrollController _scrollController;
24+
2325
int _unreadMessagesCount = 0;
2426
List<MessageDVO>? _messages;
2527
List<LocalRequestDVO>? _requests;
@@ -31,6 +33,8 @@ class _HomeViewState extends State<HomeView> {
3133
void initState() {
3234
super.initState();
3335

36+
_scrollController = ScrollController();
37+
3438
_reload();
3539

3640
final runtime = GetIt.I.get<EnmeshedRuntime>();
@@ -46,6 +50,8 @@ class _HomeViewState extends State<HomeView> {
4650

4751
@override
4852
void dispose() {
53+
_scrollController.dispose();
54+
4955
for (final subscription in _subscriptions) {
5056
subscription.cancel();
5157
}
@@ -67,8 +73,10 @@ class _HomeViewState extends State<HomeView> {
6773
return RefreshIndicator(
6874
onRefresh: () => _reload(syncBefore: true),
6975
child: Scrollbar(
76+
controller: _scrollController,
7077
thumbVisibility: true,
7178
child: ListView(
79+
controller: _scrollController,
7280
children: [
7381
Padding(
7482
padding: const EdgeInsets.symmetric(horizontal: 16),

apps/enmeshed/lib/core/setup_push.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import 'package:logger/logger.dart';
99
import 'package:push/push.dart';
1010

1111
Future<void> setupPush(EnmeshedRuntime runtime) async {
12+
if (Platform.isWindows) return;
13+
1214
final logger = GetIt.I.get<Logger>();
1315

1416
// this will timeout e.g. on the ios simulator

apps/enmeshed/lib/main.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:async';
2+
import 'dart:io';
23

34
import 'package:croppy/croppy.dart';
45
import 'package:enmeshed_runtime_bridge/enmeshed_runtime_bridge.dart';
@@ -26,7 +27,7 @@ import 'splash_screen.dart';
2627

2728
void main() async {
2829
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
29-
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
30+
if (Platform.isAndroid || Platform.isIOS) FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
3031

3132
timeago.setLocaleMessages('de', timeago.DeMessages());
3233
timeago.setLocaleMessages('en', timeago.EnMessages());

apps/enmeshed/lib/splash_screen.dart

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:go_router/go_router.dart';
1111
import 'package:logger/logger.dart';
1212
import 'package:permission_handler/permission_handler.dart';
1313
import 'package:renderers/renderers.dart';
14+
import 'package:win32_registry/win32_registry.dart';
1415

1516
import 'core/core.dart';
1617

@@ -64,17 +65,20 @@ class _SplashScreenState extends State<SplashScreen> {
6465
Future<void> _init(GoRouter router) async {
6566
await GetIt.I.reset();
6667

68+
final logger = Logger(printer: SimplePrinter(colors: false));
69+
GetIt.I.registerSingleton(logger);
70+
GetIt.I.registerSingleton<AbstractUrlLauncher>(UrlLauncher());
71+
6772
// TODO(jkoenig134): we should probably ask for permission when we need it
68-
await Permission.camera.request();
73+
final cameraStatus = await Permission.camera.request();
74+
if (!cameraStatus.isGranted) {
75+
logger.w('Camera permission is (permanently) denied');
76+
}
6977

7078
if (Platform.isAndroid && kDebugMode) {
7179
await InAppWebViewController.setWebContentsDebuggingEnabled(true);
7280
}
7381

74-
final logger = Logger(printer: SimplePrinter(colors: false));
75-
GetIt.I.registerSingleton(logger);
76-
GetIt.I.registerSingleton<AbstractUrlLauncher>(UrlLauncher());
77-
7882
final runtime = EnmeshedRuntime(
7983
logger: logger,
8084
runtimeConfig: (
@@ -87,6 +91,7 @@ class _SplashScreenState extends State<SplashScreen> {
8791
),
8892
);
8993
GetIt.I.registerSingletonAsync<EnmeshedRuntime>(() async => runtime.run());
94+
9095
await GetIt.I.allReady();
9196

9297
await setupPush(runtime);
@@ -101,10 +106,10 @@ class _SplashScreenState extends State<SplashScreen> {
101106

102107
await runtime.registerUIBridge(AppUIBridge(logger: logger, router: router));
103108

109+
await _registerWindowsSchemeForDebugMode('nmshd-dev');
110+
104111
final appLinks = AppLinks();
105-
appLinks.uriLinkStream.listen((Uri? uri) {
106-
if (uri != null) GetIt.I.get<EnmeshedRuntime>().stringProcessor.processURL(url: uri.toString());
107-
});
112+
appLinks.uriLinkStream.listen(_processUri);
108113

109114
final accounts = await runtime.accountServices.getAccounts();
110115
final accountsNotInDeletion = await runtime.accountServices.getAccountsNotInDeletion();
@@ -123,8 +128,33 @@ class _SplashScreenState extends State<SplashScreen> {
123128
}
124129

125130
final initialAppLink = await appLinks.getInitialLink();
126-
if (initialAppLink != null) {
127-
await GetIt.I.get<EnmeshedRuntime>().stringProcessor.processURL(url: initialAppLink.toString());
131+
await _processUri(initialAppLink);
132+
}
133+
134+
Future<void> _processUri(Uri? uri) async {
135+
if (uri == null) return;
136+
137+
final uriString = uri.toString().replaceAll('nmshd-dev://', 'nmshd://').replaceAll('qr/#', 'qr#');
138+
GetIt.I.get<Logger>().i("Processing URL '$uriString'");
139+
140+
final result = await GetIt.I.get<EnmeshedRuntime>().stringProcessor.processURL(url: uriString);
141+
if (result.isError) {
142+
GetIt.I.get<Logger>().e("Processing URL '$uriString' failed with code '${result.error.code}' and message '${result.error.message}'");
128143
}
129144
}
130145
}
146+
147+
Future<void> _registerWindowsSchemeForDebugMode(String scheme) async {
148+
if (!Platform.isWindows || !kDebugMode) return;
149+
150+
final appPath = Platform.resolvedExecutable;
151+
152+
final protocolRegKey = 'Software\\Classes\\$scheme';
153+
const protocolRegValue = RegistryValue('URL Protocol', RegistryValueType.string, '');
154+
const protocolCmdRegKey = r'shell\open\command';
155+
final protocolCmdRegValue = RegistryValue('', RegistryValueType.string, '"$appPath" "%1"');
156+
157+
Registry.currentUser.createKey(protocolRegKey)
158+
..createValue(protocolRegValue)
159+
..createKey(protocolCmdRegKey).createValue(protocolCmdRegValue);
160+
}

apps/enmeshed/pubspec.lock

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ packages:
137137
url: "https://pub.dev"
138138
source: hosted
139139
version: "1.19.0"
140+
console:
141+
dependency: transitive
142+
description:
143+
name: console
144+
sha256: e04e7824384c5b39389acdd6dc7d33f3efe6b232f6f16d7626f194f6a01ad69a
145+
url: "https://pub.dev"
146+
source: hosted
147+
version: "4.1.0"
140148
croppy:
141149
dependency: "direct main"
142150
description:
@@ -762,6 +770,15 @@ packages:
762770
url: "https://pub.dev"
763771
source: hosted
764772
version: "6.0.2"
773+
msix:
774+
dependency: "direct dev"
775+
description:
776+
path: "."
777+
ref: "Fix-Flutter-3.27"
778+
resolved-ref: "955467338b11ddcd789a37d268e9cfd884a94b17"
779+
url: "https://github.com/h4h13/msix.git"
780+
source: git
781+
version: "3.16.8"
765782
open_file:
766783
dependency: "direct main"
767784
description:
@@ -826,6 +843,14 @@ packages:
826843
url: "https://pub.dev"
827844
source: hosted
828845
version: "0.0.3"
846+
package_config:
847+
dependency: transitive
848+
description:
849+
name: package_config
850+
sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67"
851+
url: "https://pub.dev"
852+
source: hosted
853+
version: "2.1.1"
829854
package_info_plus:
830855
dependency: "direct main"
831856
description:
@@ -1002,6 +1027,14 @@ packages:
10021027
url: "https://pub.dev"
10031028
source: hosted
10041029
version: "5.13.4"
1030+
pub_semver:
1031+
dependency: transitive
1032+
description:
1033+
name: pub_semver
1034+
sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd"
1035+
url: "https://pub.dev"
1036+
source: hosted
1037+
version: "2.1.5"
10051038
push:
10061039
dependency: "direct main"
10071040
description:
@@ -1373,6 +1406,22 @@ packages:
13731406
url: "https://pub.dev"
13741407
source: hosted
13751408
version: "5.10.0"
1409+
win32_registry:
1410+
dependency: "direct main"
1411+
description:
1412+
name: win32_registry
1413+
sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852"
1414+
url: "https://pub.dev"
1415+
source: hosted
1416+
version: "1.1.5"
1417+
windows_notification:
1418+
dependency: transitive
1419+
description:
1420+
name: windows_notification
1421+
sha256: be3e650874615f315402c9b9f3656e29af156709c4b5cc272cb4ca0ab7ba94a8
1422+
url: "https://pub.dev"
1423+
source: hosted
1424+
version: "1.3.0"
13761425
wolt_modal_sheet:
13771426
dependency: "direct main"
13781427
description:

apps/enmeshed/pubspec.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,17 @@ dependencies:
5555
value_renderer: ^1.0.0
5656
vector_graphics: ^1.1.13
5757
very_good_analysis: ^6.0.0
58+
win32_registry: ^1.1.5
5859
wolt_modal_sheet: ^0.5.0
5960

6061
dev_dependencies:
6162
flutter_launcher_icons: ^0.14.1
6263
flutter_test:
6364
sdk: flutter
65+
msix:
66+
git:
67+
url: https://github.com/h4h13/msix.git
68+
ref: Fix-Flutter-3.27
6469
translations_cleaner: ^0.0.5
6570
vector_graphics_compiler: ^1.1.12
6671

@@ -81,6 +86,9 @@ flutter_icons:
8186
image_path: "assets/icon.png"
8287
android: true
8388
ios: true
89+
windows:
90+
generate: true
91+
image_path: "assets/icon-512.png"
8492
remove_alpha_ios: true
8593
image_path_ios_dark_transparent: "assets/icon_dark.png"
8694
image_path_ios_tinted_grayscale: "assets/icon_grayscale.png"
@@ -104,3 +112,19 @@ flutter_native_splash:
104112

105113
android: true
106114
ios: true
115+
116+
# dart run msix:create
117+
msix_config:
118+
display_name: enmeshed
119+
publisher_display_name: js-soft
120+
identity_name: js-soft.enmeshed
121+
publisher: CN=CB3048C3-A086-471C-AF11-83ABB7396C98
122+
store: true
123+
protocol_activation: nmshd
124+
logo_path: assets/icon-512.png
125+
start_menu_icon_path: assets/icon-512.png
126+
tile_icon_path: assets/icon-512.png
127+
icons_background_color: transparent
128+
build_windows: false
129+
languages: en-us, de-de
130+
# capabilities: "internetClient,internetClientServer,privateNetworkClientServer"

apps/enmeshed/windows/.gitignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
flutter/ephemeral/
2+
3+
# Visual Studio user-specific files.
4+
*.suo
5+
*.user
6+
*.userosscache
7+
*.sln.docstates
8+
9+
# Visual Studio build-related files.
10+
x64/
11+
x86/
12+
13+
# Visual Studio cache files
14+
# files ending in .cache can be ignored
15+
*.[Cc]ache
16+
# but keep track of directories ending in .cache
17+
!*.[Cc]ache/

0 commit comments

Comments
 (0)