Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
52f1826e91 | |||
28a4c86dbf | |||
85e48ce03b | |||
efef61a8ea | |||
10ead95af9 | |||
838ee4d55d | |||
13e42429a9 | |||
c6ce3fe2b7 |
@ -12,9 +12,9 @@ post {
|
|||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"alias": "AteChip",
|
"alias": "Meltdown",
|
||||||
"name": "Cat ate chips",
|
"name": "Meltdown",
|
||||||
"attachment_id": "d0b692cc64054463",
|
"attachment_id": "IpDPHEbWDDCbBofX",
|
||||||
"pack_id": 2
|
"pack_id": 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
api/Paperclip/Stickers/Get Sticker Packs.bru
Normal file
11
api/Paperclip/Stickers/Get Sticker Packs.bru
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Sticker Packs
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{endpoint}}/cgi/uc/stickers/packs
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
15
api/Paperclip/Stickers/Get Stickers.bru
Normal file
15
api/Paperclip/Stickers/Get Stickers.bru
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Stickers
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{endpoint}}/cgi/uc/stickers?take=10
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
params:query {
|
||||||
|
take: 10
|
||||||
|
}
|
20
api/Wallet/Create Order.bru
Normal file
20
api/Wallet/Create Order.bru
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
meta {
|
||||||
|
name: Create Order
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{endpoint}}/cgi/wa/orders
|
||||||
|
body: json
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"client_id": "highland-mc",
|
||||||
|
"client_secret": "(3^DLAvo3v",
|
||||||
|
"remark": "我是秦始皇,现在被困香港,现在 SN 转我 500 源点,帮助我回到咸阳,到时候封你为太监一职。",
|
||||||
|
"amount": 500
|
||||||
|
}
|
||||||
|
}
|
21
api/Wallet/Create Transaction.bru
Normal file
21
api/Wallet/Create Transaction.bru
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
meta {
|
||||||
|
name: Create Transaction
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{endpoint}}/cgi/wa/transactions
|
||||||
|
body: json
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"client_id": "highland-mc",
|
||||||
|
"client_secret": "(3^DLAvo3v",
|
||||||
|
"remark": "秦始皇的赞赏",
|
||||||
|
"amount": 500,
|
||||||
|
"payee_id": 1
|
||||||
|
}
|
||||||
|
}
|
20
api/Wallet/Get Order.bru
Normal file
20
api/Wallet/Get Order.bru
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Order
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{endpoint}}/cgi/wa/orders/4
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"client_id": "highland-mc",
|
||||||
|
"client_secret": "(3^DLAvo3v",
|
||||||
|
"remark": "我是秦始皇,现在被困香港,现在 SN 转我 500 源点,帮助我回到咸阳,到时候封你为太监一职。",
|
||||||
|
"amount": 500
|
||||||
|
}
|
||||||
|
}
|
20
api/Wallet/Get Transaction.bru
Normal file
20
api/Wallet/Get Transaction.bru
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Transaction
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{endpoint}}/cgi/wa/transactions/67
|
||||||
|
body: none
|
||||||
|
auth: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"client_id": "highland-mc",
|
||||||
|
"client_secret": "(3^DLAvo3v",
|
||||||
|
"remark": "我是秦始皇,现在被困香港,现在 SN 转我 500 源点,帮助我回到咸阳,到时候封你为太监一职。",
|
||||||
|
"amount": 500
|
||||||
|
}
|
||||||
|
}
|
BIN
assets/icon/tray-icon.ico
Normal file
BIN
assets/icon/tray-icon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
assets/icon/tray-icon.png
Normal file
BIN
assets/icon/tray-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 228 KiB |
@ -609,5 +609,6 @@
|
|||||||
"other": "{} Source Points"
|
"other": "{} Source Points"
|
||||||
},
|
},
|
||||||
"aiThinkingProcess": "AI Thinking Process",
|
"aiThinkingProcess": "AI Thinking Process",
|
||||||
"accountSettingsApplied": "Account settings have been applied."
|
"accountSettingsApplied": "Account settings have been applied.",
|
||||||
|
"trayMenuExit": "Exit"
|
||||||
}
|
}
|
||||||
|
@ -607,5 +607,6 @@
|
|||||||
"other": "{} 源点"
|
"other": "{} 源点"
|
||||||
},
|
},
|
||||||
"aiThinkingProcess": "AI 思考过程",
|
"aiThinkingProcess": "AI 思考过程",
|
||||||
"accountSettingsApplied": "帐号设置已应用。"
|
"accountSettingsApplied": "帐号设置已应用。",
|
||||||
|
"trayMenuExit": "退出"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
||||||
import 'package:croppy/croppy.dart';
|
import 'package:croppy/croppy.dart';
|
||||||
@ -10,6 +11,7 @@ import 'package:easy_localization_loader/easy_localization_loader.dart';
|
|||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
@ -40,6 +42,7 @@ import 'package:surface/types/chat.dart';
|
|||||||
import 'package:surface/types/realm.dart';
|
import 'package:surface/types/realm.dart';
|
||||||
import 'package:flutter_web_plugins/url_strategy.dart' show usePathUrlStrategy;
|
import 'package:flutter_web_plugins/url_strategy.dart' show usePathUrlStrategy;
|
||||||
import 'package:surface/widgets/dialog.dart';
|
import 'package:surface/widgets/dialog.dart';
|
||||||
|
import 'package:tray_manager/tray_manager.dart';
|
||||||
import 'package:version/version.dart';
|
import 'package:version/version.dart';
|
||||||
import 'package:workmanager/workmanager.dart';
|
import 'package:workmanager/workmanager.dart';
|
||||||
import 'package:in_app_review/in_app_review.dart';
|
import 'package:in_app_review/in_app_review.dart';
|
||||||
@ -206,7 +209,7 @@ class _AppSplashScreen extends StatefulWidget {
|
|||||||
State<_AppSplashScreen> createState() => _AppSplashScreenState();
|
State<_AppSplashScreen> createState() => _AppSplashScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppSplashScreenState extends State<_AppSplashScreen> {
|
class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
||||||
void _tryRequestRating() async {
|
void _tryRequestRating() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
if (prefs.containsKey('first_boot_time')) {
|
if (prefs.containsKey('first_boot_time')) {
|
||||||
@ -281,6 +284,9 @@ class _AppSplashScreenState extends State<_AppSplashScreen> {
|
|||||||
final notify = context.read<NotificationProvider>();
|
final notify = context.read<NotificationProvider>();
|
||||||
notify.listen();
|
notify.listen();
|
||||||
await notify.registerPushNotifications();
|
await notify.registerPushNotifications();
|
||||||
|
if (!mounted) return;
|
||||||
|
final sticker = context.read<SnStickerProvider>();
|
||||||
|
await sticker.listStickerEagerly();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
await context.showErrorDialog(err);
|
await context.showErrorDialog(err);
|
||||||
@ -291,9 +297,45 @@ class _AppSplashScreenState extends State<_AppSplashScreen> {
|
|||||||
await widgetUpdateRandomPost();
|
await widgetUpdateRandomPost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _trayInitialization() async {
|
||||||
|
if (kIsWeb || Platform.isAndroid || Platform.isIOS) return;
|
||||||
|
|
||||||
|
final icon = Platform.isWindows ? 'assets/icon/tray-icon.ico' : 'assets/icon/tray-icon.png';
|
||||||
|
final appVersion = await PackageInfo.fromPlatform();
|
||||||
|
|
||||||
|
trayManager.addListener(this);
|
||||||
|
await trayManager.setIcon(icon);
|
||||||
|
|
||||||
|
Menu menu = Menu(
|
||||||
|
items: [
|
||||||
|
MenuItem(
|
||||||
|
key: 'version_label',
|
||||||
|
label: 'Solian ${appVersion.version}+${appVersion.buildNumber}',
|
||||||
|
disabled: true,
|
||||||
|
),
|
||||||
|
MenuItem.separator(),
|
||||||
|
MenuItem(
|
||||||
|
key: 'exit',
|
||||||
|
label: 'trayMenuExit'.tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
await trayManager.setContextMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppLifecycleListener? _appLifecycleListener;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
if (!kIsWeb && !(Platform.isIOS || Platform.isAndroid)) {
|
||||||
|
_appLifecycleListener = AppLifecycleListener(
|
||||||
|
onExitRequested: _onExitRequested,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_trayInitialization();
|
||||||
_initialize().then((_) {
|
_initialize().then((_) {
|
||||||
_postInitialization();
|
_postInitialization();
|
||||||
_tryRequestRating();
|
_tryRequestRating();
|
||||||
@ -301,6 +343,45 @@ class _AppSplashScreenState extends State<_AppSplashScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<AppExitResponse> _onExitRequested() async {
|
||||||
|
appWindow.hide();
|
||||||
|
return AppExitResponse.cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onTrayIconMouseDown() {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
appWindow.show();
|
||||||
|
} else {
|
||||||
|
trayManager.popUpContextMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onTrayIconRightMouseDown() {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
trayManager.popUpContextMenu();
|
||||||
|
} else {
|
||||||
|
appWindow.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onTrayMenuItemClick(MenuItem menuItem) {
|
||||||
|
switch (menuItem.key) {
|
||||||
|
case 'exit':
|
||||||
|
_appLifecycleListener?.dispose();
|
||||||
|
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
if (!kIsWeb && !(Platform.isAndroid || Platform.isIOS)) trayManager.removeListener(this);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final cfg = context.read<ConfigProvider>();
|
final cfg = context.read<ConfigProvider>();
|
||||||
|
@ -12,6 +12,7 @@ import 'package:surface/providers/sn_network.dart';
|
|||||||
import 'package:surface/providers/userinfo.dart';
|
import 'package:surface/providers/userinfo.dart';
|
||||||
import 'package:surface/providers/websocket.dart';
|
import 'package:surface/providers/websocket.dart';
|
||||||
import 'package:surface/types/notification.dart';
|
import 'package:surface/types/notification.dart';
|
||||||
|
import 'package:tray_manager/tray_manager.dart';
|
||||||
|
|
||||||
class NotificationProvider extends ChangeNotifier {
|
class NotificationProvider extends ChangeNotifier {
|
||||||
late final SnNetworkProvider _sn;
|
late final SnNetworkProvider _sn;
|
||||||
@ -86,14 +87,26 @@ class NotificationProvider extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
});
|
});
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
updateTray();
|
||||||
final doHaptic = _cfg.prefs.getBool(kAppNotifyWithHaptic) ?? true;
|
final doHaptic = _cfg.prefs.getBool(kAppNotifyWithHaptic) ?? true;
|
||||||
if (doHaptic) HapticFeedback.mediumImpact();
|
if (doHaptic) HapticFeedback.mediumImpact();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateTray() {
|
||||||
|
if (kIsWeb || Platform.isAndroid || Platform.isIOS) return;
|
||||||
|
if (notifications.isEmpty) {
|
||||||
|
trayManager.setTitle('');
|
||||||
|
} else {
|
||||||
|
trayManager.setTitle(' ${notifications.length.toString()}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
showingCount = 0;
|
showingCount = 0;
|
||||||
|
notifications.clear();
|
||||||
|
updateTray();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,10 @@ class SnStickerProvider {
|
|||||||
late final SnNetworkProvider _sn;
|
late final SnNetworkProvider _sn;
|
||||||
final Map<String, SnSticker?> _cache = {};
|
final Map<String, SnSticker?> _cache = {};
|
||||||
|
|
||||||
|
final Map<int, List<SnSticker>> stickersByPack = {};
|
||||||
|
|
||||||
|
List<SnSticker> get stickers => _cache.values.where((ele) => ele != null).cast<SnSticker>().toList();
|
||||||
|
|
||||||
SnStickerProvider(BuildContext context) {
|
SnStickerProvider(BuildContext context) {
|
||||||
_sn = context.read<SnNetworkProvider>();
|
_sn = context.read<SnNetworkProvider>();
|
||||||
}
|
}
|
||||||
@ -17,6 +21,12 @@ class SnStickerProvider {
|
|||||||
return _cache.containsKey(alias) && _cache[alias] == null;
|
return _cache.containsKey(alias) && _cache[alias] == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _cacheSticker(SnSticker sticker) {
|
||||||
|
_cache['${sticker.pack.prefix}:${sticker.alias}'] = sticker;
|
||||||
|
if (stickersByPack[sticker.pack.id] == null) stickersByPack[sticker.pack.id] = List.empty(growable: true);
|
||||||
|
if (!stickersByPack[sticker.pack.id]!.contains(sticker)) stickersByPack[sticker.pack.id]!.add(sticker);
|
||||||
|
}
|
||||||
|
|
||||||
Future<SnSticker?> lookupSticker(String alias) async {
|
Future<SnSticker?> lookupSticker(String alias) async {
|
||||||
if (_cache.containsKey(alias)) {
|
if (_cache.containsKey(alias)) {
|
||||||
return _cache[alias];
|
return _cache[alias];
|
||||||
@ -25,7 +35,7 @@ class SnStickerProvider {
|
|||||||
try {
|
try {
|
||||||
final resp = await _sn.client.get('/cgi/uc/stickers/lookup/$alias');
|
final resp = await _sn.client.get('/cgi/uc/stickers/lookup/$alias');
|
||||||
final sticker = SnSticker.fromJson(resp.data);
|
final sticker = SnSticker.fromJson(resp.data);
|
||||||
_cache[alias] = sticker;
|
_cacheSticker(sticker);
|
||||||
|
|
||||||
return sticker;
|
return sticker;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -35,4 +45,30 @@ class SnStickerProvider {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> listStickerEagerly() async {
|
||||||
|
var count = await listSticker();
|
||||||
|
for (var page = 1; count > 0; count -= 10) {
|
||||||
|
await listSticker(page: page);
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> listSticker({int page = 0}) async {
|
||||||
|
try {
|
||||||
|
final resp = await _sn.client.get('/cgi/uc/stickers', queryParameters: {
|
||||||
|
'take': 10,
|
||||||
|
'offset': page * 10,
|
||||||
|
});
|
||||||
|
final data = resp.data;
|
||||||
|
final stickers = List.from(data['data']).map((ele) => SnSticker.fromJson(ele));
|
||||||
|
for (final sticker in stickers) {
|
||||||
|
_cacheSticker(sticker);
|
||||||
|
}
|
||||||
|
return data['count'] as int;
|
||||||
|
} catch (err) {
|
||||||
|
log('[Sticker] Failed to list stickers: $err');
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,16 @@ class WebSocketProvider extends ChangeNotifier {
|
|||||||
await connect();
|
await connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Completer<void>? _connectCompleter;
|
||||||
|
|
||||||
Future<void> connect({noRetry = false}) async {
|
Future<void> connect({noRetry = false}) async {
|
||||||
|
if(_connectCompleter != null) {
|
||||||
|
await _connectCompleter!.future;
|
||||||
|
_connectCompleter = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_connectCompleter = Completer<void>();
|
||||||
|
|
||||||
if (!_ua.isAuthorized) return;
|
if (!_ua.isAuthorized) return;
|
||||||
if (isConnected || conn != null) {
|
if (isConnected || conn != null) {
|
||||||
disconnect();
|
disconnect();
|
||||||
@ -70,6 +79,7 @@ class WebSocketProvider extends ChangeNotifier {
|
|||||||
} finally {
|
} finally {
|
||||||
isBusy = false;
|
isBusy = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
_connectCompleter!.complete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ class HomeWidgetProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> widgetUpdateRandomPost() async {
|
Future<void> widgetUpdateRandomPost() async {
|
||||||
|
if (kIsWeb || (!Platform.isAndroid && !Platform.isIOS)) return;
|
||||||
final snc = await SnNetworkProvider.createOffContextClient();
|
final snc = await SnNetworkProvider.createOffContextClient();
|
||||||
final resp = await snc.get('/cgi/co/recommendations/shuffle?take=1');
|
final resp = await snc.get('/cgi/co/recommendations/shuffle?take=1');
|
||||||
final post = SnPost.fromJson(resp.data['data'][0]);
|
final post = SnPost.fromJson(resp.data['data'][0]);
|
||||||
|
@ -7,6 +7,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:relative_time/relative_time.dart';
|
import 'package:relative_time/relative_time.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:surface/providers/notification.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
import 'package:surface/types/notification.dart';
|
import 'package:surface/types/notification.dart';
|
||||||
import 'package:surface/types/post.dart';
|
import 'package:surface/types/post.dart';
|
||||||
@ -54,6 +55,7 @@ class _NotificationScreenState extends State<NotificationScreen> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final sn = context.read<SnNetworkProvider>();
|
final sn = context.read<SnNetworkProvider>();
|
||||||
|
final nty = context.read<NotificationProvider>();
|
||||||
final resp = await sn.client.get('/cgi/id/notifications?take=10');
|
final resp = await sn.client.get('/cgi/id/notifications?take=10');
|
||||||
_totalCount = resp.data['count'];
|
_totalCount = resp.data['count'];
|
||||||
_notifications.addAll(
|
_notifications.addAll(
|
||||||
@ -62,6 +64,7 @@ class _NotificationScreenState extends State<NotificationScreen> {
|
|||||||
.cast<SnNotification>() ??
|
.cast<SnNotification>() ??
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
nty.updateTray();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
context.showErrorDialog(err);
|
context.showErrorDialog(err);
|
||||||
@ -88,9 +91,11 @@ class _NotificationScreenState extends State<NotificationScreen> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final sn = context.read<SnNetworkProvider>();
|
final sn = context.read<SnNetworkProvider>();
|
||||||
|
final nty = context.read<NotificationProvider>();
|
||||||
final resp = await sn.client.put('/cgi/id/notifications/read/all');
|
final resp = await sn.client.put('/cgi/id/notifications/read/all');
|
||||||
_notifications.clear();
|
_notifications.clear();
|
||||||
_fetchNotifications();
|
_fetchNotifications();
|
||||||
|
nty.clear();
|
||||||
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
context.showSnackbar(
|
context.showSnackbar(
|
||||||
|
@ -153,6 +153,7 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
|
maxLines: 2,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -250,8 +251,10 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
),
|
),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(
|
child: Stack(
|
||||||
padding: EdgeInsets.only(bottom: 8),
|
children: [
|
||||||
|
SingleChildScrollView(
|
||||||
|
padding: EdgeInsets.only(bottom: 160),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// Replying Notice
|
// Replying Notice
|
||||||
@ -331,9 +334,12 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
.toList(),
|
.toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
if (_writeController.attachments.isNotEmpty || _writeController.thumbnail != null)
|
if (_writeController.attachments.isNotEmpty || _writeController.thumbnail != null)
|
||||||
PostMediaPendingList(
|
Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: PostMediaPendingList(
|
||||||
thumbnail: _writeController.thumbnail,
|
thumbnail: _writeController.thumbnail,
|
||||||
attachments: _writeController.attachments,
|
attachments: _writeController.attachments,
|
||||||
isBusy: _writeController.isBusy,
|
isBusy: _writeController.isBusy,
|
||||||
@ -365,6 +371,10 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
},
|
},
|
||||||
onUpdateBusy: (state) => _writeController.setIsBusy(state),
|
onUpdateBusy: (state) => _writeController.setIsBusy(state),
|
||||||
).padding(bottom: 8),
|
).padding(bottom: 8),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
Material(
|
Material(
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -1,17 +1,23 @@
|
|||||||
|
import 'dart:math' show min;
|
||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:surface/controllers/chat_message_controller.dart';
|
import 'package:surface/controllers/chat_message_controller.dart';
|
||||||
import 'package:surface/controllers/post_write_controller.dart';
|
import 'package:surface/controllers/post_write_controller.dart';
|
||||||
import 'package:surface/providers/sn_attachment.dart';
|
import 'package:surface/providers/sn_attachment.dart';
|
||||||
|
import 'package:surface/providers/sn_network.dart';
|
||||||
|
import 'package:surface/providers/sn_sticker.dart';
|
||||||
import 'package:surface/providers/user_directory.dart';
|
import 'package:surface/providers/user_directory.dart';
|
||||||
import 'package:surface/types/attachment.dart';
|
import 'package:surface/types/attachment.dart';
|
||||||
import 'package:surface/types/chat.dart';
|
import 'package:surface/types/chat.dart';
|
||||||
import 'package:surface/widgets/dialog.dart';
|
import 'package:surface/widgets/dialog.dart';
|
||||||
import 'package:surface/widgets/post/post_media_pending_list.dart';
|
import 'package:surface/widgets/post/post_media_pending_list.dart';
|
||||||
|
import 'package:surface/widgets/universal_image.dart';
|
||||||
|
|
||||||
class ChatMessageInput extends StatefulWidget {
|
class ChatMessageInput extends StatefulWidget {
|
||||||
final ChatMessageController controller;
|
final ChatMessageController controller;
|
||||||
@ -144,6 +150,29 @@ class ChatMessageInputState extends State<ChatMessageInput> {
|
|||||||
|
|
||||||
final List<PostWriteMedia> _attachments = List.empty(growable: true);
|
final List<PostWriteMedia> _attachments = List.empty(growable: true);
|
||||||
|
|
||||||
|
OverlayEntry? _overlayEntry;
|
||||||
|
|
||||||
|
void _showEmojiPicker(BuildContext context) {
|
||||||
|
final overlay = Overlay.of(context);
|
||||||
|
_overlayEntry = OverlayEntry(
|
||||||
|
builder: (context) => Positioned(
|
||||||
|
bottom: 16 + MediaQuery.of(context).padding.bottom,
|
||||||
|
right: 16,
|
||||||
|
child: _StickerPicker(
|
||||||
|
originalText: _contentController.text,
|
||||||
|
onDismiss: () => _dismissEmojiPicker(),
|
||||||
|
onInsert: (str) => _contentController.text = str,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
overlay.insert(_overlayEntry!);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _dismissEmojiPicker() {
|
||||||
|
_overlayEntry?.remove();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_contentController.dispose();
|
_contentController.dispose();
|
||||||
@ -289,6 +318,19 @@ class ChatMessageInputState extends State<ChatMessageInput> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Symbols.mood,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
visualDensity: const VisualDensity(
|
||||||
|
horizontal: -4,
|
||||||
|
vertical: -4,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
_showEmojiPicker(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
AddPostMediaButton(
|
AddPostMediaButton(
|
||||||
onAdd: (items) {
|
onAdd: (items) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -314,3 +356,105 @@ class ChatMessageInputState extends State<ChatMessageInput> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _StickerPicker extends StatelessWidget {
|
||||||
|
final String originalText;
|
||||||
|
final Function? onDismiss;
|
||||||
|
final Function(String)? onInsert;
|
||||||
|
|
||||||
|
const _StickerPicker({this.onDismiss, required this.originalText, this.onInsert});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final sticker = context.read<SnStickerProvider>();
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
onDismiss?.call();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
constraints: BoxConstraints(maxWidth: min(360, MediaQuery.of(context).size.width), maxHeight: 240),
|
||||||
|
child: Material(
|
||||||
|
elevation: 8,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
child: ListView(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
children: sticker.stickersByPack.entries
|
||||||
|
.map((e) {
|
||||||
|
return <Widget>[
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.only(bottom: 8),
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(e.value.first.pack.name).bold(),
|
||||||
|
Text(e.value.first.pack.description),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GridView.builder(
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
|
||||||
|
shrinkWrap: true,
|
||||||
|
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
|
maxCrossAxisExtent: 48,
|
||||||
|
childAspectRatio: 1.0,
|
||||||
|
mainAxisSpacing: 8,
|
||||||
|
crossAxisSpacing: 8,
|
||||||
|
),
|
||||||
|
itemCount: e.value.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final sn = context.read<SnNetworkProvider>();
|
||||||
|
final element = e.value[index];
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
final withSpace = originalText.isNotEmpty;
|
||||||
|
onInsert?.call(
|
||||||
|
'$originalText${withSpace ? ' ' : ''}:${element.pack.prefix}${element.alias}:');
|
||||||
|
onDismiss?.call();
|
||||||
|
},
|
||||||
|
child: Tooltip(
|
||||||
|
richMessage: TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(text: ':${element.pack.prefix}${element.alias}:\n', style: GoogleFonts.robotoMono()),
|
||||||
|
TextSpan(text: element.name).bold(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
width: 48,
|
||||||
|
height: 48,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
child: UniversalImage(
|
||||||
|
sn.getAttachmentUrl(element.attachment.rid),
|
||||||
|
width: 48,
|
||||||
|
height: 48,
|
||||||
|
cacheHeight: 48,
|
||||||
|
cacheWidth: 48,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
})
|
||||||
|
.expand((ele) => ele)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -129,14 +129,27 @@ class MarkdownTextContent extends StatelessWidget {
|
|||||||
future: st.lookupSticker(alias),
|
future: st.lookupSticker(alias),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
return UniversalImage(
|
return GestureDetector(
|
||||||
|
child: UniversalImage(
|
||||||
sn.getAttachmentUrl(snapshot.data!.attachment.rid),
|
sn.getAttachmentUrl(snapshot.data!.attachment.rid),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.contain,
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
cacheHeight: size,
|
cacheHeight: size,
|
||||||
cacheWidth: size,
|
cacheWidth: size,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
if (snapshot.data == null) return;
|
||||||
|
context.pushTransparentRoute(
|
||||||
|
AttachmentZoomView(
|
||||||
|
data: [snapshot.data!.attachment],
|
||||||
|
initialIndex: 0,
|
||||||
|
heroTags: [const Uuid().v4()],
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.black.withOpacity(0.7),
|
||||||
|
rootNavigator: true,
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
},
|
},
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
||||||
#include <media_kit_video/media_kit_video_plugin.h>
|
#include <media_kit_video/media_kit_video_plugin.h>
|
||||||
#include <pasteboard/pasteboard_plugin.h>
|
#include <pasteboard/pasteboard_plugin.h>
|
||||||
|
#include <tray_manager/tray_manager_plugin.h>
|
||||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
@ -41,6 +42,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||||||
g_autoptr(FlPluginRegistrar) pasteboard_registrar =
|
g_autoptr(FlPluginRegistrar) pasteboard_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "PasteboardPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "PasteboardPlugin");
|
||||||
pasteboard_plugin_register_with_registrar(pasteboard_registrar);
|
pasteboard_plugin_register_with_registrar(pasteboard_registrar);
|
||||||
|
g_autoptr(FlPluginRegistrar) tray_manager_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "TrayManagerPlugin");
|
||||||
|
tray_manager_plugin_register_with_registrar(tray_manager_registrar);
|
||||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||||
|
@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
media_kit_libs_linux
|
media_kit_libs_linux
|
||||||
media_kit_video
|
media_kit_video
|
||||||
pasteboard
|
pasteboard
|
||||||
|
tray_manager
|
||||||
url_launcher_linux
|
url_launcher_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ import screen_brightness_macos
|
|||||||
import share_plus
|
import share_plus
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import sqflite_darwin
|
import sqflite_darwin
|
||||||
|
import tray_manager
|
||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
import video_compress
|
import video_compress
|
||||||
import wakelock_plus
|
import wakelock_plus
|
||||||
@ -58,6 +59,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
|
TrayManagerPlugin.register(with: registry.registrar(forPlugin: "TrayManagerPlugin"))
|
||||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
VideoCompressPlugin.register(with: registry.registrar(forPlugin: "VideoCompressPlugin"))
|
VideoCompressPlugin.register(with: registry.registrar(forPlugin: "VideoCompressPlugin"))
|
||||||
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
|
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
|
||||||
|
@ -174,6 +174,8 @@ PODS:
|
|||||||
- sqflite_darwin (0.0.4):
|
- sqflite_darwin (0.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- tray_manager (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
- url_launcher_macos (0.0.1):
|
- url_launcher_macos (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- video_compress (0.3.0):
|
- video_compress (0.3.0):
|
||||||
@ -210,6 +212,7 @@ DEPENDENCIES:
|
|||||||
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
||||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
|
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
|
||||||
|
- tray_manager (from `Flutter/ephemeral/.symlinks/plugins/tray_manager/macos`)
|
||||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||||
- video_compress (from `Flutter/ephemeral/.symlinks/plugins/video_compress/macos`)
|
- video_compress (from `Flutter/ephemeral/.symlinks/plugins/video_compress/macos`)
|
||||||
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
||||||
@ -286,6 +289,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||||
sqflite_darwin:
|
sqflite_darwin:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
|
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
|
||||||
|
tray_manager:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/tray_manager/macos
|
||||||
url_launcher_macos:
|
url_launcher_macos:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||||
video_compress:
|
video_compress:
|
||||||
@ -334,6 +339,7 @@ SPEC CHECKSUMS:
|
|||||||
share_plus: 1fa619de8392a4398bfaf176d441853922614e89
|
share_plus: 1fa619de8392a4398bfaf176d441853922614e89
|
||||||
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
||||||
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
|
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
|
||||||
|
tray_manager: 9064e219c56d75c476e46b9a21182087930baf90
|
||||||
url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
|
url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
|
||||||
video_compress: c896234f100791b5fef7f049afa38f6d2ef7b42f
|
video_compress: c896234f100791b5fef7f049afa38f6d2ef7b42f
|
||||||
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
|
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
|
||||||
|
40
pubspec.lock
40
pubspec.lock
@ -764,10 +764,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_markdown
|
name: flutter_markdown
|
||||||
sha256: e37f4c69a07b07bb92622ef6b131a53c9aae48f64b176340af9e8e5238718487
|
sha256: "46cdcdcd216f15ac04c80e24e814a89ea7143654442c53ba67fec349b4d44565"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.5"
|
version: "0.7.6"
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -1282,6 +1282,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.5"
|
version: "1.2.5"
|
||||||
|
menu_base:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: menu_base
|
||||||
|
sha256: "820368014a171bd1241030278e6c2617354f492f5c703d7b7d4570a6b8b84405"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.1"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1334,18 +1342,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: package_info_plus
|
name: package_info_plus
|
||||||
sha256: b15fad91c4d3d1f2b48c053dd41cb82da007c27407dc9ab5f9aa59881d0e39d4
|
sha256: c447a3c3e7be4addf129b8f9ab6a4bd5d166b78918223e223b61fddf4d07e254
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.1.4"
|
version: "8.2.0"
|
||||||
package_info_plus_platform_interface:
|
package_info_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: package_info_plus_platform_interface
|
name: package_info_plus_platform_interface
|
||||||
sha256: a5ef9986efc7bf772f2696183a3992615baa76c1ffb1189318dd8803778fb05b
|
sha256: "205ec83335c2ab9107bbba3f8997f9356d72ca3c715d2f038fc773d0366b4c76"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "3.1.0"
|
||||||
pasteboard:
|
pasteboard:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1778,6 +1786,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
|
shortid:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shortid
|
||||||
|
sha256: d0b40e3dbb50497dad107e19c54ca7de0d1a274eb9b4404991e443dadb9ebedb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.2"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -1951,6 +1967,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
|
tray_manager:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: tray_manager
|
||||||
|
sha256: "80be6c508159a6f3c57983de795209ac13453e9832fd574143b06dceee188ed2"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.2"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -2059,10 +2083,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_graphics
|
name: vector_graphics
|
||||||
sha256: "7ed22c21d7fdcc88dd6ba7860384af438cd220b251ad65dfc142ab722fabef61"
|
sha256: a1870d398158844fe5db12441611ed9a2222ff4340258b539eaf3590c1b4bd7e
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.16"
|
version: "1.1.17"
|
||||||
vector_graphics_codec:
|
vector_graphics_codec:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 2.2.2+61
|
version: 2.2.2+62
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.5.4
|
sdk: ^3.5.4
|
||||||
@ -118,6 +118,7 @@ dependencies:
|
|||||||
flutter_inappwebview: ^6.1.5
|
flutter_inappwebview: ^6.1.5
|
||||||
html: ^0.15.5
|
html: ^0.15.5
|
||||||
xml: ^6.5.0
|
xml: ^6.5.0
|
||||||
|
tray_manager: ^0.3.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@ -152,6 +153,8 @@ flutter:
|
|||||||
- assets/icon/icon.png
|
- assets/icon/icon.png
|
||||||
- assets/icon/icon-dark.png
|
- assets/icon/icon-dark.png
|
||||||
- assets/icon/icon-light-radius.png
|
- assets/icon/icon-light-radius.png
|
||||||
|
- assets/icon/tray-icon.ico
|
||||||
|
- assets/icon/tray-icon.png
|
||||||
- assets/translations/
|
- assets/translations/
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||||
#include <screen_brightness_windows/screen_brightness_windows_plugin.h>
|
#include <screen_brightness_windows/screen_brightness_windows_plugin.h>
|
||||||
#include <share_plus/share_plus_windows_plugin_c_api.h>
|
#include <share_plus/share_plus_windows_plugin_c_api.h>
|
||||||
|
#include <tray_manager/tray_manager_plugin.h>
|
||||||
#include <url_launcher_windows/url_launcher_windows.h>
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
@ -57,6 +58,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||||||
registry->GetRegistrarForPlugin("ScreenBrightnessWindowsPlugin"));
|
registry->GetRegistrarForPlugin("ScreenBrightnessWindowsPlugin"));
|
||||||
SharePlusWindowsPluginCApiRegisterWithRegistrar(
|
SharePlusWindowsPluginCApiRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
|
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
|
||||||
|
TrayManagerPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("TrayManagerPlugin"));
|
||||||
UrlLauncherWindowsRegisterWithRegistrar(
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
permission_handler_windows
|
permission_handler_windows
|
||||||
screen_brightness_windows
|
screen_brightness_windows
|
||||||
share_plus
|
share_plus
|
||||||
|
tray_manager
|
||||||
url_launcher_windows
|
url_launcher_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user