mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-11-20 02:59:26 +01:00
Merge branch 'braid/windows' into 'main'
chore: Windows support See merge request famedly/fluffychat!949
This commit is contained in:
commit
6d23ea754f
@ -391,9 +391,11 @@ upload-windows:
|
|||||||
image: alpine:latest
|
image: alpine:latest
|
||||||
script:
|
script:
|
||||||
- apk add --no-cache curl zip
|
- apk add --no-cache curl zip
|
||||||
|
- mv build/windows/runner/Release/fluffychat.msix fluffychat.msix
|
||||||
- cd build/windows/runner/Release; zip -r ../../../../package.zip . ; cd -
|
- cd build/windows/runner/Release; zip -r ../../../../package.zip . ; cd -
|
||||||
- |
|
- |
|
||||||
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.zip ${PACKAGE_REGISTRY_URL}/fluffychat-windows.zip
|
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.zip ${PACKAGE_REGISTRY_URL}/fluffychat-windows.zip
|
||||||
|
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file fluffychat.msix ${PACKAGE_REGISTRY_URL}/fluffychat-windows.msix
|
||||||
|
|
||||||
upload-playstore:
|
upload-playstore:
|
||||||
stage: release
|
stage: release
|
||||||
@ -416,6 +418,7 @@ release:
|
|||||||
--assets-link "{\"name\":\"fluffychat-linux-x86.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/fluffychat-linux-x86.tar.gz\"}" \
|
--assets-link "{\"name\":\"fluffychat-linux-x86.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/fluffychat-linux-x86.tar.gz\"}" \
|
||||||
--assets-link "{\"name\":\"fluffychat-linux-arm64.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/fluffychat-linux-arm64.tar.gz\"}" \
|
--assets-link "{\"name\":\"fluffychat-linux-arm64.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/fluffychat-linux-arm64.tar.gz\"}" \
|
||||||
--assets-link "{\"name\":\"fluffychat-windows.zip\",\"url\":\"${PACKAGE_REGISTRY_URL}/fluffychat-windows.zip\"}" \
|
--assets-link "{\"name\":\"fluffychat-windows.zip\",\"url\":\"${PACKAGE_REGISTRY_URL}/fluffychat-windows.zip\"}" \
|
||||||
|
--assets-link "{\"name\":\"fluffychat-windows.msix\",\"url\":\"${PACKAGE_REGISTRY_URL}/fluffychat-windows.msix\"}" \
|
||||||
--assets-link "{\"name\":\"fluffychat-web.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/fluffychat-web.tar.gz\"}"
|
--assets-link "{\"name\":\"fluffychat-web.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/fluffychat-web.tar.gz\"}"
|
||||||
--assets-link "{\"name\":\"FluffyChat-x86_64.AppImage\",\"url\":\"${PACKAGE_REGISTRY_URL}/FluffyChat-x86_64.AppImage\",\"filepath\":\"/FluffyChat-x86_64.AppImage\"}"
|
--assets-link "{\"name\":\"FluffyChat-x86_64.AppImage\",\"url\":\"${PACKAGE_REGISTRY_URL}/FluffyChat-x86_64.AppImage\",\"filepath\":\"/FluffyChat-x86_64.AppImage\"}"
|
||||||
--assets-link "{\"name\":\"FluffyChat-x86_64.AppImage.zsync\",\"url\":\"${PACKAGE_REGISTRY_URL}/FluffyChat-x86_64.AppImage.zsync\",\"filepath\":\"/FluffyChat-x86_64.AppImage.zsync\"}"
|
--assets-link "{\"name\":\"FluffyChat-x86_64.AppImage.zsync\",\"url\":\"${PACKAGE_REGISTRY_URL}/FluffyChat-x86_64.AppImage.zsync\",\"filepath\":\"/FluffyChat-x86_64.AppImage.zsync\"}"
|
||||||
|
15
.metadata
15
.metadata
@ -15,21 +15,6 @@ migration:
|
|||||||
- platform: root
|
- platform: root
|
||||||
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
||||||
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
||||||
- platform: android
|
|
||||||
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
|
||||||
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
|
||||||
- platform: ios
|
|
||||||
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
|
||||||
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
|
||||||
- platform: linux
|
|
||||||
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
|
||||||
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
|
||||||
- platform: macos
|
|
||||||
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
|
||||||
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
|
||||||
- platform: web
|
|
||||||
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
|
||||||
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
|
||||||
- platform: windows
|
- platform: windows
|
||||||
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
||||||
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"updateAvailable": "FluffyChat update available",
|
||||||
|
"updateNow": "Start update in background",
|
||||||
"accept": "Accept",
|
"accept": "Accept",
|
||||||
"@accept": {
|
"@accept": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
116
lib/utils/update_checker_no_store.dart
Normal file
116
lib/utils/update_checker_no_store.dart
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:matrix/matrix.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
|
import 'platform_infos.dart';
|
||||||
|
|
||||||
|
/// helper class checking for updates on platforms without store release
|
||||||
|
///
|
||||||
|
/// Currently, this is only Windows
|
||||||
|
class UpdateCheckerNoStore {
|
||||||
|
static const gitLabProjectId = '16112282';
|
||||||
|
static const gitLabHost = 'gitlab.com';
|
||||||
|
|
||||||
|
static Uri get tagsUri => Uri.parse(
|
||||||
|
'https://$gitLabHost/projects/$gitLabProjectId/repository/tags');
|
||||||
|
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
|
const UpdateCheckerNoStore(this.context);
|
||||||
|
|
||||||
|
Future<void> checkUpdate() async {
|
||||||
|
// platform-specific implementations
|
||||||
|
try {
|
||||||
|
if (PlatformInfos.isWindows) {
|
||||||
|
final response = await get(tagsUri);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final json = jsonDecode(response.body);
|
||||||
|
var latestTag = json[0]['name'] as String;
|
||||||
|
var currentVersion = await PlatformInfos.getVersion();
|
||||||
|
|
||||||
|
if (latestTag.startsWith('v')) {
|
||||||
|
latestTag = latestTag.substring(1);
|
||||||
|
}
|
||||||
|
if (currentVersion.startsWith('v')) {
|
||||||
|
currentVersion = currentVersion.substring(1);
|
||||||
|
}
|
||||||
|
if (latestTag != currentVersion) {
|
||||||
|
final metadata = UpdateMetadata(latestTag);
|
||||||
|
await showUpdateDialog(metadata);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
throw response;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Logs().i('Could not look for updates:', e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri downloadUri(UpdateMetadata metadata) {
|
||||||
|
// platform specific
|
||||||
|
if (PlatformInfos.isWindows) {
|
||||||
|
return Uri.parse('https://$gitLabHost/famedly/fluffychat/-'
|
||||||
|
'/jobs/artifacts/$metadata/raw/'
|
||||||
|
'build/windows/runner/Release/fluffychat.msix?job=build_windows');
|
||||||
|
} else {
|
||||||
|
throw UnimplementedError('No download URI available for this platform.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// launches an app update
|
||||||
|
///
|
||||||
|
/// Either uses the operating systems package or app management to perform
|
||||||
|
/// an update or launches a custom installer
|
||||||
|
Future<void> launchUpdater(UpdateMetadata metadata) async {
|
||||||
|
// platform specific
|
||||||
|
try {
|
||||||
|
if (kIsWeb) return;
|
||||||
|
if (PlatformInfos.isWindows) {
|
||||||
|
final dir = await getTemporaryDirectory();
|
||||||
|
final response = await get(downloadUri(metadata));
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final file = File(dir.path + '/fluffychat.msix');
|
||||||
|
await file.writeAsBytes(response.bodyBytes);
|
||||||
|
Process.start(file.path, [], runInShell: true);
|
||||||
|
} else {
|
||||||
|
throw response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Logs().w('Error launching th update:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> showUpdateDialog(UpdateMetadata metadata) async {
|
||||||
|
final result = await showOkCancelAlertDialog(
|
||||||
|
title: L10n.of(context)!.updateAvailable,
|
||||||
|
message: L10n.of(context)!.updateNow,
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
if (result == OkCancelResult.ok) {
|
||||||
|
await launchUpdater(metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateMetadata {
|
||||||
|
final String version;
|
||||||
|
|
||||||
|
const UpdateMetadata(this.version);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'v$version';
|
||||||
|
}
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:vrouter/vrouter.dart';
|
import 'package:vrouter/vrouter.dart';
|
||||||
|
|
||||||
|
import 'package:fluffychat/utils/update_checker_no_store.dart';
|
||||||
import 'package:fluffychat/widgets/layouts/empty_page.dart';
|
import 'package:fluffychat/widgets/layouts/empty_page.dart';
|
||||||
import 'package:fluffychat/widgets/matrix.dart';
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
|
|
||||||
@ -12,13 +13,16 @@ class LoadingView extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback(
|
WidgetsBinding.instance.addPostFrameCallback(
|
||||||
(_) => VRouter.of(context).to(
|
(_) async {
|
||||||
Matrix.of(context).widget.clients.any((client) =>
|
await UpdateCheckerNoStore(context).checkUpdate();
|
||||||
client.onLoginStateChanged.value == LoginState.loggedIn)
|
VRouter.of(context).to(
|
||||||
? '/rooms'
|
Matrix.of(context).widget.clients.any((client) =>
|
||||||
: '/home',
|
client.onLoginStateChanged.value == LoginState.loggedIn)
|
||||||
queryParameters: VRouter.of(context).queryParameters,
|
? '/rooms'
|
||||||
),
|
: '/home',
|
||||||
|
queryParameters: VRouter.of(context).queryParameters,
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
return const EmptyPage(loading: true);
|
return const EmptyPage(loading: true);
|
||||||
}
|
}
|
||||||
|
40
pubspec.lock
40
pubspec.lock
@ -162,6 +162,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.3.1"
|
||||||
|
cli_dialog:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cli_dialog
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.0"
|
||||||
cli_util:
|
cli_util:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -276,6 +283,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.12.0"
|
version: "4.12.0"
|
||||||
|
dart_console:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dart_console
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
dart_style:
|
dart_style:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -684,11 +698,13 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
flutter_secure_storage_windows:
|
flutter_secure_storage_windows:
|
||||||
dependency: transitive
|
dependency: "direct overridden"
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage_windows
|
path: "."
|
||||||
url: "https://pub.dartlang.org"
|
ref: main
|
||||||
source: hosted
|
resolved-ref: "3751da0df5eede20d64816ceb79ca78ace7389b3"
|
||||||
|
url: "https://gitlab.com/TheOneWithTheBraid/flutter_secure_storage_windows.git"
|
||||||
|
source: git
|
||||||
version: "1.1.2"
|
version: "1.1.2"
|
||||||
flutter_slidable:
|
flutter_slidable:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
@ -789,6 +805,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.6"
|
version: "2.0.6"
|
||||||
|
get_it:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: get_it
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "7.2.0"
|
||||||
glob:
|
glob:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -839,7 +862,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
http:
|
http:
|
||||||
dependency: "direct dev"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
@ -1090,6 +1113,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
|
msix:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: msix
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.6.2"
|
||||||
native_imaging:
|
native_imaging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
22
pubspec.yaml
22
pubspec.yaml
@ -53,6 +53,7 @@ dependencies:
|
|||||||
geolocator: ^7.6.2
|
geolocator: ^7.6.2
|
||||||
handy_window: ^0.1.6
|
handy_window: ^0.1.6
|
||||||
hive_flutter: ^1.1.0
|
hive_flutter: ^1.1.0
|
||||||
|
http: ^0.13.4
|
||||||
image: ^3.1.1
|
image: ^3.1.1
|
||||||
image_picker: ^0.8.4+8
|
image_picker: ^0.8.4+8
|
||||||
intl: any
|
intl: any
|
||||||
@ -96,10 +97,10 @@ dev_dependencies:
|
|||||||
flutter_native_splash: ^2.0.3+1
|
flutter_native_splash: ^2.0.3+1
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
http: ^0.13.4
|
|
||||||
import_sorter: ^4.6.0
|
import_sorter: ^4.6.0
|
||||||
integration_test:
|
integration_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
msix: ^3.6.2
|
||||||
|
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
color: "#ffffff"
|
color: "#ffffff"
|
||||||
@ -127,6 +128,19 @@ flutter:
|
|||||||
fonts:
|
fonts:
|
||||||
- asset: fonts/NotoEmoji/NotoColorEmoji.ttf
|
- asset: fonts/NotoEmoji/NotoColorEmoji.ttf
|
||||||
|
|
||||||
|
msix_config:
|
||||||
|
display_name: FluffyChat
|
||||||
|
publisher_display_name: FluffyChat
|
||||||
|
publisher: CN=FluffyChat, O=Head of bad integration tests, L=Matrix, S=Internet, C=EU
|
||||||
|
identity_name: chat.fluffy.fluffychat
|
||||||
|
logo_path: assets\logo.png
|
||||||
|
capabilities: internetClient, location, microphone, webcam
|
||||||
|
protocol_activation: https
|
||||||
|
app_uri_handler_hosts: fluffychat.im, matrix.to
|
||||||
|
execution_alias: fluffychat
|
||||||
|
sign_msix: false
|
||||||
|
install_certificate: false
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
# Necessary for webRTC on web.
|
# Necessary for webRTC on web.
|
||||||
# Fix for stream fallback for unsupported browsers:
|
# Fix for stream fallback for unsupported browsers:
|
||||||
@ -136,6 +150,12 @@ dependency_overrides:
|
|||||||
url: https://github.com/TheOneWithTheBraid/plus_plugins.git
|
url: https://github.com/TheOneWithTheBraid/plus_plugins.git
|
||||||
ref: a04401cb48abe92d138c0e9288b360739994a9e9
|
ref: a04401cb48abe92d138c0e9288b360739994a9e9
|
||||||
path: packages/connectivity_plus/connectivity_plus_web
|
path: packages/connectivity_plus/connectivity_plus_web
|
||||||
|
# fake secure storage plugin for Windows
|
||||||
|
# See: https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15161
|
||||||
|
flutter_secure_storage_windows:
|
||||||
|
git:
|
||||||
|
url: https://gitlab.com/TheOneWithTheBraid/flutter_secure_storage_windows.git
|
||||||
|
ref: main
|
||||||
geolocator_android:
|
geolocator_android:
|
||||||
hosted:
|
hosted:
|
||||||
name: geolocator_android
|
name: geolocator_android
|
||||||
|
@ -2,4 +2,11 @@ flutter doctor
|
|||||||
flutter config --enable-windows-desktop
|
flutter config --enable-windows-desktop
|
||||||
flutter clean
|
flutter clean
|
||||||
flutter pub get
|
flutter pub get
|
||||||
|
|
||||||
|
Write-Output "$WINDOWN_PFX"
|
||||||
|
Move-Item -Path $WINDOWS_PFX -Destination fluffychat.pem
|
||||||
|
certutil -decode fluffychat.pem fluffychat.pfx
|
||||||
|
|
||||||
flutter build windows --release -v
|
flutter build windows --release -v
|
||||||
|
|
||||||
|
flutter pub run msix:create -c fluffychat.pfx -p $WINDOWS_PFX_PASS --sign-msix true --install-certificate false
|
@ -1,3 +1,5 @@
|
|||||||
choco install flutter -y
|
choco install flutter -y
|
||||||
Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
|
Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
|
||||||
refreshenv
|
refreshenv
|
||||||
|
|
||||||
|
flutter config --no-analytics
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
# Project-level configuration.
|
||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
project(fluffychat LANGUAGES CXX)
|
project(fluffychat LANGUAGES CXX)
|
||||||
|
|
||||||
|
# The name of the executable created for the application. Change this to change
|
||||||
|
# the on-disk name of your application.
|
||||||
set(BINARY_NAME "fluffychat")
|
set(BINARY_NAME "fluffychat")
|
||||||
|
|
||||||
|
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||||
|
# versions of CMake.
|
||||||
cmake_policy(SET CMP0063 NEW)
|
cmake_policy(SET CMP0063 NEW)
|
||||||
|
|
||||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
# Define build configuration option.
|
||||||
|
|
||||||
# Configure build options.
|
|
||||||
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||||
if(IS_MULTICONFIG)
|
if(IS_MULTICONFIG)
|
||||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
|
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
|
||||||
@ -20,7 +23,7 @@ else()
|
|||||||
"Debug" "Profile" "Release")
|
"Debug" "Profile" "Release")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
# Define settings for the Profile build mode.
|
||||||
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
|
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
|
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
|
||||||
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
|
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
|
||||||
@ -30,6 +33,10 @@ set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
|
|||||||
add_definitions(-DUNICODE -D_UNICODE)
|
add_definitions(-DUNICODE -D_UNICODE)
|
||||||
|
|
||||||
# Compilation settings that should be applied to most targets.
|
# Compilation settings that should be applied to most targets.
|
||||||
|
#
|
||||||
|
# Be cautious about adding new options here, as plugins use this function by
|
||||||
|
# default. In most cases, you should add new options to specific targets instead
|
||||||
|
# of modifying this function.
|
||||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||||
target_compile_features(${TARGET} PUBLIC cxx_std_17)
|
target_compile_features(${TARGET} PUBLIC cxx_std_17)
|
||||||
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
|
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
|
||||||
@ -38,12 +45,11 @@ function(APPLY_STANDARD_SETTINGS TARGET)
|
|||||||
target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
|
target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
|
||||||
|
|
||||||
# Flutter library and tool build rules.
|
# Flutter library and tool build rules.
|
||||||
|
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||||
|
|
||||||
# Application build
|
# Application build; see runner/CMakeLists.txt.
|
||||||
add_subdirectory("runner")
|
add_subdirectory("runner")
|
||||||
|
|
||||||
# Generated plugin build rules, which manage building the plugins and adding
|
# Generated plugin build rules, which manage building the plugins and adding
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
# This file controls Flutter-level build steps. It should not be edited.
|
||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
|
||||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ list(APPEND FLUTTER_LIBRARY_HEADERS
|
|||||||
"flutter_windows.h"
|
"flutter_windows.h"
|
||||||
"flutter_messenger.h"
|
"flutter_messenger.h"
|
||||||
"flutter_plugin_registrar.h"
|
"flutter_plugin_registrar.h"
|
||||||
|
"flutter_texture_registrar.h"
|
||||||
)
|
)
|
||||||
list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
|
list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
|
||||||
add_library(flutter INTERFACE)
|
add_library(flutter INTERFACE)
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include <connectivity_plus_windows/connectivity_plus_windows_plugin.h>
|
#include <connectivity_plus_windows/connectivity_plus_windows_plugin.h>
|
||||||
#include <desktop_drop/desktop_drop_plugin.h>
|
#include <desktop_drop/desktop_drop_plugin.h>
|
||||||
#include <desktop_lifecycle/desktop_lifecycle_plugin.h>
|
#include <desktop_lifecycle/desktop_lifecycle_plugin.h>
|
||||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
|
||||||
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
||||||
#include <record_windows/record_windows_plugin_c_api.h>
|
#include <record_windows/record_windows_plugin_c_api.h>
|
||||||
#include <url_launcher_windows/url_launcher_windows.h>
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
@ -21,8 +20,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||||||
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
|
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
|
||||||
DesktopLifecyclePluginRegisterWithRegistrar(
|
DesktopLifecyclePluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("DesktopLifecyclePlugin"));
|
registry->GetRegistrarForPlugin("DesktopLifecyclePlugin"));
|
||||||
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
|
||||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
|
||||||
FlutterWebRTCPluginRegisterWithRegistrar(
|
FlutterWebRTCPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("FlutterWebRTCPlugin"));
|
registry->GetRegistrarForPlugin("FlutterWebRTCPlugin"));
|
||||||
RecordWindowsPluginCApiRegisterWithRegistrar(
|
RecordWindowsPluginCApiRegisterWithRegistrar(
|
||||||
|
@ -6,7 +6,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
connectivity_plus_windows
|
connectivity_plus_windows
|
||||||
desktop_drop
|
desktop_drop
|
||||||
desktop_lifecycle
|
desktop_lifecycle
|
||||||
flutter_secure_storage_windows
|
|
||||||
flutter_webrtc
|
flutter_webrtc
|
||||||
record_windows
|
record_windows
|
||||||
url_launcher_windows
|
url_launcher_windows
|
||||||
|
@ -1,18 +1,32 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
project(runner LANGUAGES CXX)
|
project(runner LANGUAGES CXX)
|
||||||
|
|
||||||
|
# Define the application target. To change its name, change BINARY_NAME in the
|
||||||
|
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
|
||||||
|
# work.
|
||||||
|
#
|
||||||
|
# Any new source files that you add to the application should be added here.
|
||||||
add_executable(${BINARY_NAME} WIN32
|
add_executable(${BINARY_NAME} WIN32
|
||||||
"flutter_window.cpp"
|
"flutter_window.cpp"
|
||||||
"main.cpp"
|
"main.cpp"
|
||||||
"run_loop.cpp"
|
|
||||||
"utils.cpp"
|
"utils.cpp"
|
||||||
"win32_window.cpp"
|
"win32_window.cpp"
|
||||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||||
"Runner.rc"
|
"Runner.rc"
|
||||||
"runner.exe.manifest"
|
"runner.exe.manifest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Apply the standard set of build settings. This can be removed for applications
|
||||||
|
# that need different build settings.
|
||||||
apply_standard_settings(${BINARY_NAME})
|
apply_standard_settings(${BINARY_NAME})
|
||||||
|
|
||||||
|
# Disable Windows macros that collide with C++ standard library functions.
|
||||||
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
|
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
|
||||||
|
|
||||||
|
# Add dependency libraries and include directories. Add any application-specific
|
||||||
|
# dependencies here.
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
|
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
|
||||||
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
|
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||||
|
|
||||||
|
# Run the Flutter tool portions of the build. This must not be removed.
|
||||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||||
|
@ -90,12 +90,12 @@ BEGIN
|
|||||||
BLOCK "040904e4"
|
BLOCK "040904e4"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "chat.fluffy" "\0"
|
VALUE "CompanyName", "chat.fluffy" "\0"
|
||||||
VALUE "FileDescription", "A new Flutter project." "\0"
|
VALUE "FileDescription", "fluffychat" "\0"
|
||||||
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||||
VALUE "InternalName", "FluffyChat" "\0"
|
VALUE "InternalName", "fluffychat" "\0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2020 chat.fluffy. All rights reserved." "\0"
|
VALUE "LegalCopyright", "Copyright (C) 2022 chat.fluffy. All rights reserved." "\0"
|
||||||
VALUE "OriginalFilename", "fluffychat.exe" "\0"
|
VALUE "OriginalFilename", "fluffychat.exe" "\0"
|
||||||
VALUE "ProductName", "FluffyChat" "\0"
|
VALUE "ProductName", "fluffychat" "\0"
|
||||||
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
#include "flutter/generated_plugin_registrant.h"
|
#include "flutter/generated_plugin_registrant.h"
|
||||||
|
|
||||||
FlutterWindow::FlutterWindow(RunLoop* run_loop,
|
FlutterWindow::FlutterWindow(const flutter::DartProject& project)
|
||||||
const flutter::DartProject& project)
|
: project_(project) {}
|
||||||
: run_loop_(run_loop), project_(project) {}
|
|
||||||
|
|
||||||
FlutterWindow::~FlutterWindow() {}
|
FlutterWindow::~FlutterWindow() {}
|
||||||
|
|
||||||
@ -26,14 +25,12 @@ bool FlutterWindow::OnCreate() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
RegisterPlugins(flutter_controller_->engine());
|
RegisterPlugins(flutter_controller_->engine());
|
||||||
run_loop_->RegisterFlutterInstance(flutter_controller_->engine());
|
|
||||||
SetChildContent(flutter_controller_->view()->GetNativeWindow());
|
SetChildContent(flutter_controller_->view()->GetNativeWindow());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlutterWindow::OnDestroy() {
|
void FlutterWindow::OnDestroy() {
|
||||||
if (flutter_controller_) {
|
if (flutter_controller_) {
|
||||||
run_loop_->UnregisterFlutterInstance(flutter_controller_->engine());
|
|
||||||
flutter_controller_ = nullptr;
|
flutter_controller_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +41,7 @@ LRESULT
|
|||||||
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
|
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
|
||||||
WPARAM const wparam,
|
WPARAM const wparam,
|
||||||
LPARAM const lparam) noexcept {
|
LPARAM const lparam) noexcept {
|
||||||
// Give Flutter, including plugins, an opporutunity to handle window messages.
|
// Give Flutter, including plugins, an opportunity to handle window messages.
|
||||||
if (flutter_controller_) {
|
if (flutter_controller_) {
|
||||||
std::optional<LRESULT> result =
|
std::optional<LRESULT> result =
|
||||||
flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
|
flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
|
||||||
|
@ -6,16 +6,13 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "run_loop.h"
|
|
||||||
#include "win32_window.h"
|
#include "win32_window.h"
|
||||||
|
|
||||||
// A window that does nothing but host a Flutter view.
|
// A window that does nothing but host a Flutter view.
|
||||||
class FlutterWindow : public Win32Window {
|
class FlutterWindow : public Win32Window {
|
||||||
public:
|
public:
|
||||||
// Creates a new FlutterWindow driven by the |run_loop|, hosting a
|
// Creates a new FlutterWindow hosting a Flutter view running |project|.
|
||||||
// Flutter view running |project|.
|
explicit FlutterWindow(const flutter::DartProject& project);
|
||||||
explicit FlutterWindow(RunLoop* run_loop,
|
|
||||||
const flutter::DartProject& project);
|
|
||||||
virtual ~FlutterWindow();
|
virtual ~FlutterWindow();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -26,9 +23,6 @@ class FlutterWindow : public Win32Window {
|
|||||||
LPARAM const lparam) noexcept override;
|
LPARAM const lparam) noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The run loop driving events for this window.
|
|
||||||
RunLoop* run_loop_;
|
|
||||||
|
|
||||||
// The project to run.
|
// The project to run.
|
||||||
flutter::DartProject project_;
|
flutter::DartProject project_;
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include "flutter_window.h"
|
#include "flutter_window.h"
|
||||||
#include "run_loop.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||||
@ -18,10 +17,14 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
|||||||
// plugins.
|
// plugins.
|
||||||
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||||
|
|
||||||
RunLoop run_loop;
|
|
||||||
|
|
||||||
flutter::DartProject project(L"data");
|
flutter::DartProject project(L"data");
|
||||||
FlutterWindow window(&run_loop, project);
|
|
||||||
|
std::vector<std::string> command_line_arguments =
|
||||||
|
GetCommandLineArguments();
|
||||||
|
|
||||||
|
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
|
||||||
|
|
||||||
|
FlutterWindow window(project);
|
||||||
Win32Window::Point origin(10, 10);
|
Win32Window::Point origin(10, 10);
|
||||||
Win32Window::Size size(1280, 720);
|
Win32Window::Size size(1280, 720);
|
||||||
if (!window.CreateAndShow(L"FluffyChat", origin, size)) {
|
if (!window.CreateAndShow(L"FluffyChat", origin, size)) {
|
||||||
@ -29,7 +32,11 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
|||||||
}
|
}
|
||||||
window.SetQuitOnClose(true);
|
window.SetQuitOnClose(true);
|
||||||
|
|
||||||
run_loop.Run();
|
::MSG msg;
|
||||||
|
while (::GetMessage(&msg, nullptr, 0, 0)) {
|
||||||
|
::TranslateMessage(&msg);
|
||||||
|
::DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
::CoUninitialize();
|
::CoUninitialize();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
#include "run_loop.h"
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
RunLoop::RunLoop() {}
|
|
||||||
|
|
||||||
RunLoop::~RunLoop() {}
|
|
||||||
|
|
||||||
void RunLoop::Run() {
|
|
||||||
MSG msg;
|
|
||||||
while (GetMessage(&msg, nullptr, 0, 0)) {
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunLoop::RegisterFlutterInstance(
|
|
||||||
flutter::FlutterEngine* flutter_instance) {
|
|
||||||
flutter_instances_.insert(flutter_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunLoop::UnregisterFlutterInstance(
|
|
||||||
flutter::FlutterEngine* flutter_instance) {
|
|
||||||
flutter_instances_.erase(flutter_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
RunLoop::TimePoint RunLoop::ProcessFlutterMessages() {
|
|
||||||
TimePoint next_event_time = TimePoint::max();
|
|
||||||
for (auto instance : flutter_instances_) {
|
|
||||||
std::chrono::nanoseconds wait_duration = instance->ProcessMessages();
|
|
||||||
if (wait_duration != std::chrono::nanoseconds::max()) {
|
|
||||||
next_event_time =
|
|
||||||
std::min(next_event_time, TimePoint::clock::now() + wait_duration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return next_event_time;
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
#ifndef RUNNER_RUN_LOOP_H_
|
|
||||||
#define RUNNER_RUN_LOOP_H_
|
|
||||||
|
|
||||||
#include <flutter/flutter_engine.h>
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
// A runloop that will service events for Flutter instances as well
|
|
||||||
// as native messages.
|
|
||||||
class RunLoop {
|
|
||||||
public:
|
|
||||||
RunLoop();
|
|
||||||
~RunLoop();
|
|
||||||
|
|
||||||
// Prevent copying
|
|
||||||
RunLoop(RunLoop const&) = delete;
|
|
||||||
RunLoop& operator=(RunLoop const&) = delete;
|
|
||||||
|
|
||||||
// Runs the run loop until the application quits.
|
|
||||||
void Run();
|
|
||||||
|
|
||||||
// Registers the given Flutter instance for event servicing.
|
|
||||||
void RegisterFlutterInstance(
|
|
||||||
flutter::FlutterEngine* flutter_instance);
|
|
||||||
|
|
||||||
// Unregisters the given Flutter instance from event servicing.
|
|
||||||
void UnregisterFlutterInstance(
|
|
||||||
flutter::FlutterEngine* flutter_instance);
|
|
||||||
|
|
||||||
private:
|
|
||||||
using TimePoint = std::chrono::steady_clock::time_point;
|
|
||||||
|
|
||||||
// Processes all currently pending messages for registered Flutter instances.
|
|
||||||
TimePoint ProcessFlutterMessages();
|
|
||||||
|
|
||||||
std::set<flutter::FlutterEngine*> flutter_instances_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // RUNNER_RUN_LOOP_H_
|
|
@ -20,3 +20,45 @@ void CreateAndAttachConsole() {
|
|||||||
FlutterDesktopResyncOutputStreams();
|
FlutterDesktopResyncOutputStreams();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> GetCommandLineArguments() {
|
||||||
|
// Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
|
||||||
|
int argc;
|
||||||
|
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||||
|
if (argv == nullptr) {
|
||||||
|
return std::vector<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> command_line_arguments;
|
||||||
|
|
||||||
|
// Skip the first argument as it's the binary name.
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
::LocalFree(argv);
|
||||||
|
|
||||||
|
return command_line_arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Utf8FromUtf16(const wchar_t* utf16_string) {
|
||||||
|
if (utf16_string == nullptr) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
int target_length = ::WideCharToMultiByte(
|
||||||
|
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
||||||
|
-1, nullptr, 0, nullptr, nullptr);
|
||||||
|
std::string utf8_string;
|
||||||
|
if (target_length == 0 || target_length > utf8_string.max_size()) {
|
||||||
|
return utf8_string;
|
||||||
|
}
|
||||||
|
utf8_string.resize(target_length);
|
||||||
|
int converted_length = ::WideCharToMultiByte(
|
||||||
|
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
||||||
|
-1, utf8_string.data(),
|
||||||
|
target_length, nullptr, nullptr);
|
||||||
|
if (converted_length == 0) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
return utf8_string;
|
||||||
|
}
|
||||||
|
@ -1,8 +1,19 @@
|
|||||||
#ifndef RUNNER_UTILS_H_
|
#ifndef RUNNER_UTILS_H_
|
||||||
#define RUNNER_UTILS_H_
|
#define RUNNER_UTILS_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
// Creates a console for the process, and redirects stdout and stderr to
|
// Creates a console for the process, and redirects stdout and stderr to
|
||||||
// it for both the runner and the Flutter library.
|
// it for both the runner and the Flutter library.
|
||||||
void CreateAndAttachConsole();
|
void CreateAndAttachConsole();
|
||||||
|
|
||||||
|
// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
|
||||||
|
// encoded in UTF-8. Returns an empty std::string on failure.
|
||||||
|
std::string Utf8FromUtf16(const wchar_t* utf16_string);
|
||||||
|
|
||||||
|
// Gets the command line arguments passed in as a std::vector<std::string>,
|
||||||
|
// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
|
||||||
|
std::vector<std::string> GetCommandLineArguments();
|
||||||
|
|
||||||
#endif // RUNNER_UTILS_H_
|
#endif // RUNNER_UTILS_H_
|
||||||
|
@ -173,7 +173,7 @@ Win32Window::MessageHandler(HWND hwnd,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case WM_SIZE:
|
case WM_SIZE: {
|
||||||
RECT rect = GetClientArea();
|
RECT rect = GetClientArea();
|
||||||
if (child_content_ != nullptr) {
|
if (child_content_ != nullptr) {
|
||||||
// Size and position the child window.
|
// Size and position the child window.
|
||||||
@ -181,6 +181,7 @@ Win32Window::MessageHandler(HWND hwnd,
|
|||||||
rect.bottom - rect.top, TRUE);
|
rect.bottom - rect.top, TRUE);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
case WM_ACTIVATE:
|
case WM_ACTIVATE:
|
||||||
if (child_content_ != nullptr) {
|
if (child_content_ != nullptr) {
|
||||||
|
Loading…
Reference in New Issue
Block a user