mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-01-11 22:40:36 +00:00
added deep links for repo urls
This commit is contained in:
parent
011f62e157
commit
f00b82ddb9
23 changed files with 353 additions and 9 deletions
|
|
@ -29,6 +29,12 @@
|
|||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
<intent-filter android:label="Add source repository">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="mangayomi" android:host="add-repo" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
|
||||
|
|
@ -39,6 +45,7 @@
|
|||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="mangayomi" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="flutter_deeplinking_enabled" android:value="false" />
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import UIKit
|
||||
import Flutter
|
||||
import Libmtorrentserver
|
||||
import app_links
|
||||
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
|
|
@ -29,6 +30,12 @@ import Libmtorrentserver
|
|||
})
|
||||
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
|
||||
if let url = AppLinks.shared.getLink(launchOptions: launchOptions) {
|
||||
AppLinks.shared.handleLink(url: url)
|
||||
return true
|
||||
}
|
||||
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,5 +62,7 @@
|
|||
<true/>
|
||||
<key>UISupportsDocumentBrowser</key>
|
||||
<true/>
|
||||
<key>FlutterDeepLinkingEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -416,5 +416,6 @@
|
|||
"remove_extensions_repo": "Repository-Link entfernen",
|
||||
"manage_manga_repo_url": "Verwalte Repository-Links für Manga",
|
||||
"manage_anime_repo_url": "Verwalte Repository-Links für Anime",
|
||||
"manage_novel_repo_url": "Verwalte Repository-Links für Novellen"
|
||||
"manage_novel_repo_url": "Verwalte Repository-Links für Novellen",
|
||||
"repo_added": "Erweiterungs-Repository hinzugefügt!"
|
||||
}
|
||||
|
|
@ -428,5 +428,6 @@
|
|||
"invalid_url_format": "Invalid URL format",
|
||||
"clear_all_sources": "Clear all sources",
|
||||
"clear_all_sources_msg": "This will completely erase all sources of the application. Are you sure you want to continue?",
|
||||
"sources_cleared": "Sources cleared!!!"
|
||||
"sources_cleared": "Sources cleared!!!",
|
||||
"repo_added": "Source repository added!"
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:app_links/app_links.dart';
|
||||
import 'package:bot_toast/bot_toast.dart';
|
||||
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
||||
|
|
@ -10,8 +12,12 @@ import 'package:google_fonts/google_fonts.dart';
|
|||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/eval/model/m_bridge.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/modules/more/data_and_storage/providers/storage_usage.dart';
|
||||
import 'package:mangayomi/modules/more/settings/appearance/providers/app_font_family.dart';
|
||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:mangayomi/router/router.dart';
|
||||
|
|
@ -21,6 +27,7 @@ import 'package:mangayomi/modules/more/settings/appearance/providers/pure_black_
|
|||
import 'package:mangayomi/modules/more/settings/appearance/providers/theme_mode_state_provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:mangayomi/src/rust/frb_generated.dart';
|
||||
import 'package:mangayomi/utils/url_protocol/api.dart';
|
||||
import 'package:media_kit/media_kit.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
|
@ -40,6 +47,9 @@ void main(List<String> args) async {
|
|||
if (!(Platform.isAndroid || Platform.isIOS)) {
|
||||
await windowManager.ensureInitialized();
|
||||
}
|
||||
if (Platform.isWindows) {
|
||||
registerProtocolHandler("mangayomi");
|
||||
}
|
||||
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.windows) {
|
||||
final availableVersion = await WebViewEnvironment.getAvailableVersion();
|
||||
if (availableVersion != null) {
|
||||
|
|
@ -73,9 +83,13 @@ class MyApp extends ConsumerStatefulWidget {
|
|||
}
|
||||
|
||||
class _MyAppState extends ConsumerState<MyApp> {
|
||||
late AppLinks _appLinks;
|
||||
StreamSubscription<Uri>? _linkSubscription;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
iniDateFormatting();
|
||||
initDeepLinks();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (ref.read(clearChapterCacheOnAppLaunchStateProvider)) {
|
||||
ref
|
||||
|
|
@ -145,4 +159,55 @@ class _MyAppState extends ConsumerState<MyApp> {
|
|||
title: 'MangaYomi',
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_linkSubscription?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> initDeepLinks() async {
|
||||
final l10n = l10nLocalizations(context);
|
||||
_appLinks = AppLinks();
|
||||
_linkSubscription = _appLinks.uriLinkStream.listen((uri) {
|
||||
switch (uri.host) {
|
||||
case "add-repo":
|
||||
final repoName = uri.queryParameters["repo_name"];
|
||||
final repoUrl = uri.queryParameters["repo_url"];
|
||||
final mangaRepoUrls = uri.queryParametersAll["manga_url"];
|
||||
final animeRepoUrls = uri.queryParametersAll["anime_url"];
|
||||
final novelRepoUrls = uri.queryParametersAll["novel_url"];
|
||||
if (mangaRepoUrls != null) {
|
||||
final mangaRepos =
|
||||
ref.read(extensionsRepoStateProvider(ItemType.manga)).toList();
|
||||
mangaRepos.addAll(mangaRepoUrls.map(
|
||||
(e) => Repo(name: repoName, jsonUrl: e, website: repoUrl)));
|
||||
ref
|
||||
.read(extensionsRepoStateProvider(ItemType.manga).notifier)
|
||||
.set(mangaRepos);
|
||||
}
|
||||
if (animeRepoUrls != null) {
|
||||
final animeRepos =
|
||||
ref.read(extensionsRepoStateProvider(ItemType.anime)).toList();
|
||||
animeRepos.addAll(animeRepoUrls.map(
|
||||
(e) => Repo(name: repoName, jsonUrl: e, website: repoUrl)));
|
||||
ref
|
||||
.read(extensionsRepoStateProvider(ItemType.anime).notifier)
|
||||
.set(animeRepos);
|
||||
}
|
||||
if (novelRepoUrls != null) {
|
||||
final novelRepos =
|
||||
ref.read(extensionsRepoStateProvider(ItemType.novel)).toList();
|
||||
novelRepos.addAll(novelRepoUrls.map(
|
||||
(e) => Repo(name: repoName, jsonUrl: e, website: repoUrl)));
|
||||
ref
|
||||
.read(extensionsRepoStateProvider(ItemType.novel).notifier)
|
||||
.set(novelRepos);
|
||||
}
|
||||
botToast(l10n.repo_added);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/category.dart';
|
||||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
|
|
@ -12,6 +13,8 @@ part 'migration.g.dart';
|
|||
Future<void> migration(Ref ref) async {
|
||||
final mangas =
|
||||
isar.mangas.filter().idIsNotNull().isMangaIsNotNull().findAllSync();
|
||||
final categories =
|
||||
isar.categorys.filter().idIsNotNull().forMangaIsNotNull().findAllSync();
|
||||
|
||||
final histories = isar.historys
|
||||
.filter()
|
||||
|
|
@ -43,6 +46,9 @@ Future<void> migration(Ref ref) async {
|
|||
for (var manga in mangas) {
|
||||
isar.mangas.putSync(manga..itemType = _convertToItemType(manga.isManga!));
|
||||
}
|
||||
for (var category in categories) {
|
||||
isar.categorys.putSync(category..forItemType = _convertToItemType(category.forManga!));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ ItemType _convertToItemType(Map<String, dynamic> backup) {
|
|||
ItemType _convertToItemTypeCategory(Map<String, dynamic> backup) {
|
||||
final forManga = backup['forManga'];
|
||||
return forManga == null
|
||||
? ItemType.values[backup['itemType'] ?? 0]
|
||||
? ItemType.values[backup['forItemType'] ?? 0]
|
||||
: forManga
|
||||
? ItemType.manga
|
||||
: ItemType.anime;
|
||||
|
|
|
|||
42
lib/utils/url_protocol/api.dart
Normal file
42
lib/utils/url_protocol/api.dart
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import 'windows_protocol.dart'
|
||||
if (dart.library.js_interop) 'web_url_protocol.dart';
|
||||
|
||||
/// Registers a protocol by [scheme] to allow for links in the form `<scheme>://...`
|
||||
/// to be processed by this application. By default, opening a link will open
|
||||
/// the executable that was used to register the scheme with the URL as the first
|
||||
/// argument passed to the executable.
|
||||
///
|
||||
/// If a protocol is already registered for the given scheme, this function will
|
||||
/// attempt to overwrite the previous handler with the current executable information.
|
||||
/// However, note that depending on process permissions, this operation may be
|
||||
/// disallowed by the underlying platform.
|
||||
///
|
||||
/// You may pass an [executable] to override the path to the executable to run
|
||||
/// when accessing the URL.
|
||||
///
|
||||
/// [arguments] is a list of arguments to be used when running the executable.
|
||||
/// If passed, the list must contain at least one element, and at least one of
|
||||
/// those elements must contain the literal value `%s` to denote the URL to open.
|
||||
/// Quoting arguments is not necessary, as this will be handled for you.
|
||||
/// Escaping the `%s` as an unprocessed literal is currently unsupported.
|
||||
void registerProtocolHandler(
|
||||
String scheme, {
|
||||
String? executable,
|
||||
List<String>? arguments,
|
||||
}) {
|
||||
WindowsProtocolHandler().register(
|
||||
scheme,
|
||||
executable: executable,
|
||||
arguments: arguments,
|
||||
);
|
||||
}
|
||||
|
||||
/// Unregisters the protocol handler with the underlying platform. The provided
|
||||
/// [scheme] will no longer be used in links.
|
||||
///
|
||||
/// Note that this will unregister a protocol by scheme regardless of which process
|
||||
/// had registered it. Unregistering a scheme that was not registered by this
|
||||
/// application is undefined and depends on platform-specific restrictions.
|
||||
void unregisterProtocolHandler(String scheme) {
|
||||
WindowsProtocolHandler().unregister(scheme);
|
||||
}
|
||||
15
lib/utils/url_protocol/protocol.dart
Normal file
15
lib/utils/url_protocol/protocol.dart
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
abstract class ProtocolHandler {
|
||||
void register(String scheme, {String? executable, List<String>? arguments});
|
||||
|
||||
void unregister(String scheme);
|
||||
|
||||
List<String> getArguments(List<String>? arguments) {
|
||||
if (arguments == null) return ['%s'];
|
||||
|
||||
if (arguments.isEmpty && !arguments.any((e) => e.contains('%s'))) {
|
||||
throw ArgumentError('arguments must contain at least 1 instance of "%s"');
|
||||
}
|
||||
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
9
lib/utils/url_protocol/web_url_protocol.dart
Normal file
9
lib/utils/url_protocol/web_url_protocol.dart
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import './protocol.dart';
|
||||
|
||||
class WindowsProtocolHandler extends ProtocolHandler {
|
||||
@override
|
||||
void register(String scheme, {String? executable, List<String>? arguments}) {}
|
||||
|
||||
@override
|
||||
void unregister(String scheme) {}
|
||||
}
|
||||
65
lib/utils/url_protocol/windows_protocol.dart
Normal file
65
lib/utils/url_protocol/windows_protocol.dart
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:win32/win32.dart';
|
||||
|
||||
import './protocol.dart';
|
||||
|
||||
const _hive = HKEY_CURRENT_USER;
|
||||
|
||||
class WindowsProtocolHandler extends ProtocolHandler {
|
||||
@override
|
||||
void register(String scheme, {String? executable, List<String>? arguments}) {
|
||||
if (defaultTargetPlatform != TargetPlatform.windows) return;
|
||||
|
||||
final prefix = _regPrefix(scheme);
|
||||
final capitalized = scheme[0].toUpperCase() + scheme.substring(1);
|
||||
final args = getArguments(arguments).map((a) => _sanitize(a));
|
||||
final cmd =
|
||||
'${executable ?? Platform.resolvedExecutable} ${args.join(' ')}';
|
||||
|
||||
_regCreateStringKey(_hive, prefix, '', 'URL:$capitalized');
|
||||
_regCreateStringKey(_hive, prefix, 'URL Protocol', '');
|
||||
_regCreateStringKey(_hive, '$prefix\\shell\\open\\command', '', cmd);
|
||||
}
|
||||
|
||||
@override
|
||||
void unregister(String scheme) {
|
||||
if (defaultTargetPlatform != TargetPlatform.windows) return;
|
||||
|
||||
final txtKey = TEXT(_regPrefix(scheme));
|
||||
try {
|
||||
RegDeleteTree(HKEY_CURRENT_USER, txtKey);
|
||||
} finally {
|
||||
free(txtKey);
|
||||
}
|
||||
}
|
||||
|
||||
String _regPrefix(String scheme) => 'SOFTWARE\\Classes\\$scheme';
|
||||
|
||||
int _regCreateStringKey(int hKey, String key, String valueName, String data) {
|
||||
final txtKey = TEXT(key);
|
||||
final txtValue = TEXT(valueName);
|
||||
final txtData = TEXT(data);
|
||||
try {
|
||||
return RegSetKeyValue(
|
||||
hKey,
|
||||
txtKey,
|
||||
txtValue,
|
||||
REG_VALUE_TYPE.REG_SZ,
|
||||
txtData,
|
||||
txtData.length * 2 + 2,
|
||||
);
|
||||
} finally {
|
||||
free(txtKey);
|
||||
free(txtValue);
|
||||
free(txtData);
|
||||
}
|
||||
}
|
||||
|
||||
String _sanitize(String value) {
|
||||
value = value.replaceAll(r'%s', '%1').replaceAll(r'"', '\\"');
|
||||
return '"$value"';
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <desktop_webview_window/desktop_webview_window_plugin.h>
|
||||
#include <flutter_qjs/flutter_qjs_plugin.h>
|
||||
#include <gtk/gtk_plugin.h>
|
||||
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
|
||||
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
||||
#include <media_kit_video/media_kit_video_plugin.h>
|
||||
|
|
@ -23,6 +24,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||
g_autoptr(FlPluginRegistrar) flutter_qjs_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterQjsPlugin");
|
||||
flutter_qjs_plugin_register_with_registrar(flutter_qjs_registrar);
|
||||
g_autoptr(FlPluginRegistrar) gtk_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin");
|
||||
gtk_plugin_register_with_registrar(gtk_registrar);
|
||||
g_autoptr(FlPluginRegistrar) isar_flutter_libs_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin");
|
||||
isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
desktop_webview_window
|
||||
flutter_qjs
|
||||
gtk
|
||||
isar_flutter_libs
|
||||
media_kit_libs_linux
|
||||
media_kit_video
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@ G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
|
|||
// Implements GApplication::activate.
|
||||
static void my_application_activate(GApplication* application) {
|
||||
MyApplication* self = MY_APPLICATION(application);
|
||||
|
||||
GList* windows = gtk_application_get_windows(GTK_APPLICATION(application));
|
||||
if (windows) {
|
||||
gtk_window_present(GTK_WINDOW(windows->data));
|
||||
return;
|
||||
}
|
||||
|
||||
GtkWindow* window =
|
||||
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
|
||||
|
||||
|
|
@ -78,7 +85,7 @@ static gboolean my_application_local_command_line(GApplication* application, gch
|
|||
g_application_activate(application);
|
||||
*exit_status = 0;
|
||||
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Implements GObject::dispose.
|
||||
|
|
@ -99,6 +106,6 @@ static void my_application_init(MyApplication* self) {}
|
|||
MyApplication* my_application_new() {
|
||||
return MY_APPLICATION(g_object_new(my_application_get_type(),
|
||||
"application-id", APPLICATION_ID,
|
||||
"flags", G_APPLICATION_NON_UNIQUE,
|
||||
"flags", G_APPLICATION_HANDLES_COMMAND_LINE | G_APPLICATION_HANDLES_OPEN,
|
||||
nullptr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import app_links
|
||||
import audio_session
|
||||
import connectivity_plus
|
||||
import flutter_inappwebview_macos
|
||||
|
|
@ -28,6 +29,7 @@ import window_manager
|
|||
import window_to_front
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
|
||||
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
|
||||
|
|
|
|||
|
|
@ -1,8 +1,19 @@
|
|||
import Cocoa
|
||||
import FlutterMacOS
|
||||
import app_links
|
||||
|
||||
@main
|
||||
class AppDelegate: FlutterAppDelegate {
|
||||
public override func application(_ application: NSApplication,
|
||||
continue userActivity: NSUserActivity,
|
||||
restorationHandler: @escaping ([any NSUserActivityRestoring]) -> Void) -> Bool {
|
||||
guard let url = AppLinks.shared.getUniversalLink(userActivity) else {
|
||||
return false
|
||||
}
|
||||
AppLinks.shared.handleLink(link: url.absoluteString)
|
||||
return false
|
||||
}
|
||||
|
||||
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,5 +33,16 @@
|
|||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>mangayomi</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>mangayomi</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
46
pubspec.lock
46
pubspec.lock
|
|
@ -38,6 +38,38 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.13.2"
|
||||
app_links:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: app_links
|
||||
sha256: "433df2e61b10519407475d7f69e470789d23d593f28224c38ba1068597be7950"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.3"
|
||||
app_links_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_linux
|
||||
sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
app_links_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_platform_interface
|
||||
sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
app_links_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_web
|
||||
sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
archive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -796,6 +828,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
gtk:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: gtk
|
||||
sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
html:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -2060,13 +2100,13 @@ packages:
|
|||
source: hosted
|
||||
version: "3.16.3"
|
||||
win32:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: win32
|
||||
sha256: "154360849a56b7b67331c21f09a386562d88903f90a1099c5987afc1912e1f29"
|
||||
sha256: daf97c9d80197ed7b619040e86c8ab9a9dad285e7671ee7390f9180cc828a51e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.10.0"
|
||||
version: "5.10.1"
|
||||
window_manager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ dependencies:
|
|||
flutter_widget_from_html: ^0.15.3
|
||||
convert: ^3.1.2
|
||||
connectivity_plus: ^6.1.2
|
||||
app_links: ^6.3.3
|
||||
win32: ^5.10.1
|
||||
|
||||
dependency_overrides:
|
||||
http: ^1.2.2
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <app_links/app_links_plugin_c_api.h>
|
||||
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||
#include <flutter_inappwebview_windows/flutter_inappwebview_windows_plugin_c_api.h>
|
||||
#include <flutter_qjs/flutter_qjs_plugin.h>
|
||||
|
|
@ -21,6 +22,8 @@
|
|||
#include <window_to_front/window_to_front_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
AppLinksPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("AppLinksPluginCApi"));
|
||||
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
|
||||
FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
app_links
|
||||
connectivity_plus
|
||||
flutter_inappwebview_windows
|
||||
flutter_qjs
|
||||
|
|
|
|||
|
|
@ -4,9 +4,51 @@
|
|||
|
||||
#include "flutter_window.h"
|
||||
#include "utils.h"
|
||||
#include "app_links/app_links_plugin_c_api.h"
|
||||
|
||||
bool SendAppLinkToInstance(const std::wstring& title) {
|
||||
// Find our exact window
|
||||
HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", title.c_str());
|
||||
|
||||
if (hwnd) {
|
||||
// Dispatch new link to current window
|
||||
SendAppLink(hwnd);
|
||||
|
||||
// (Optional) Restore our window to front in same state
|
||||
WINDOWPLACEMENT place = { sizeof(WINDOWPLACEMENT) };
|
||||
GetWindowPlacement(hwnd, &place);
|
||||
|
||||
switch(place.showCmd) {
|
||||
case SW_SHOWMAXIMIZED:
|
||||
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
|
||||
break;
|
||||
case SW_SHOWMINIMIZED:
|
||||
ShowWindow(hwnd, SW_RESTORE);
|
||||
break;
|
||||
default:
|
||||
ShowWindow(hwnd, SW_NORMAL);
|
||||
break;
|
||||
}
|
||||
|
||||
SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
|
||||
SetForegroundWindow(hwnd);
|
||||
// END (Optional) Restore
|
||||
|
||||
// Window has been found, don't create another one.
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
_In_ wchar_t *command_line, _In_ int show_command) {
|
||||
// Replace "example" with the generated title found as parameter of `window.Create` in this file.
|
||||
// You may ignore the result if you need to create another window.
|
||||
if (SendAppLinkToInstance(L"Mangayomi")) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Attach to console when present (e.g., 'flutter run') or create a
|
||||
// new console when running with a debugger.
|
||||
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
|
||||
|
|
@ -40,4 +82,4 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
|||
|
||||
::CoUninitialize();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue