Compare commits
5 Commits
3.1.0+122
...
b2c5d64fc5
Author | SHA1 | Date | |
---|---|---|---|
|
b2c5d64fc5 | ||
|
5371637b16 | ||
|
c5cbf0af37 | ||
|
1a31e22450 | ||
|
49db54529d |
@@ -51,6 +51,12 @@ android {
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
|
||||
isMinifyEnabled = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,7 +64,7 @@ android {
|
||||
dependencies {
|
||||
implementation("com.google.android.material:material:1.12.0")
|
||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||
implementation("com.squareup.okhttp3:okhttp:5.1.0")
|
||||
}
|
||||
|
||||
flutter {
|
||||
|
5
android/app/proguard-rules.pro
vendored
Normal file
5
android/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# JNI Zero initialization (required for WebRTC native method registration)
|
||||
-keep class livekit.org.jni_zero.JniInit {
|
||||
# Keep the init method un-obfuscated for native code callback
|
||||
private static java.lang.Object[] init();
|
||||
}
|
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip
|
||||
|
@@ -18,11 +18,11 @@ pluginManagement {
|
||||
|
||||
plugins {
|
||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||
id("com.android.application") version "8.10.1" apply false
|
||||
id("com.android.application") version "8.12.0" apply false
|
||||
// START: FlutterFire Configuration
|
||||
id("com.google.gms.google-services") version("4.3.15") apply false
|
||||
// END: FlutterFire Configuration
|
||||
id("org.jetbrains.kotlin.android") version "1.8.22" apply false
|
||||
id("org.jetbrains.kotlin.android") version("2.2.0") apply false
|
||||
}
|
||||
|
||||
include(":app")
|
||||
|
@@ -28,6 +28,7 @@ import 'package:relative_time/relative_time.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
|
||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||
import 'package:island/widgets/keyboard_navigation.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
import 'package:flutter_langdetect/flutter_langdetect.dart' as langdetect;
|
||||
|
||||
@@ -244,30 +245,32 @@ class IslandApp extends HookConsumerWidget {
|
||||
|
||||
final router = ref.watch(routerProvider);
|
||||
|
||||
return MaterialApp.router(
|
||||
theme: theme?.light,
|
||||
darkTheme: theme?.dark,
|
||||
themeMode: ThemeMode.system,
|
||||
routerConfig: router,
|
||||
supportedLocales: context.supportedLocales,
|
||||
localizationsDelegates: [
|
||||
...context.localizationDelegates,
|
||||
CroppyLocalizations.delegate,
|
||||
RelativeTimeLocalizations.delegate,
|
||||
],
|
||||
locale: context.locale,
|
||||
builder: (context, child) {
|
||||
return Overlay(
|
||||
key: globalOverlay,
|
||||
initialEntries: [
|
||||
OverlayEntry(
|
||||
builder:
|
||||
(_) =>
|
||||
WindowScaffold(child: child ?? const SizedBox.shrink()),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
return KeyboardNavigation(
|
||||
child: MaterialApp.router(
|
||||
theme: theme?.light,
|
||||
darkTheme: theme?.dark,
|
||||
themeMode: ThemeMode.system,
|
||||
routerConfig: router,
|
||||
supportedLocales: context.supportedLocales,
|
||||
localizationsDelegates: [
|
||||
...context.localizationDelegates,
|
||||
CroppyLocalizations.delegate,
|
||||
RelativeTimeLocalizations.delegate,
|
||||
],
|
||||
locale: context.locale,
|
||||
builder: (context, child) {
|
||||
return Overlay(
|
||||
key: globalOverlay,
|
||||
initialEntries: [
|
||||
OverlayEntry(
|
||||
builder:
|
||||
(_) =>
|
||||
WindowScaffold(child: child ?? const SizedBox.shrink()),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ class StickersScreen extends HookConsumerWidget {
|
||||
context
|
||||
.pushNamed(
|
||||
'creatorStickerPackNew',
|
||||
queryParameters: {'name': pubName},
|
||||
pathParameters: {'name': pubName},
|
||||
)
|
||||
.then((value) {
|
||||
if (value != null) {
|
||||
@@ -187,10 +187,8 @@ class EditStickerPacksScreen extends HookConsumerWidget {
|
||||
'description': descriptionController.text,
|
||||
'prefix': prefixController.text,
|
||||
},
|
||||
options: Options(
|
||||
method: packId == null ? 'POST' : 'PATCH',
|
||||
headers: {'X-Pub': pubName},
|
||||
),
|
||||
queryParameters: {'pub': pubName},
|
||||
options: Options(method: packId == null ? 'POST' : 'PATCH'),
|
||||
);
|
||||
if (!context.mounted) return;
|
||||
context.pop(SnStickerPack.fromJson(resp.data));
|
||||
|
@@ -67,6 +67,9 @@ Future<void> subscribePushNotification(
|
||||
Dio apiClient, {
|
||||
bool detailedErrors = false,
|
||||
}) async {
|
||||
if (Platform.isLinux){
|
||||
return;
|
||||
}
|
||||
await FirebaseMessaging.instance.requestPermission(
|
||||
alert: true,
|
||||
badge: true,
|
||||
|
86
lib/widgets/keyboard_navigation.dart
Normal file
86
lib/widgets/keyboard_navigation.dart
Normal file
@@ -0,0 +1,86 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
enum VimMode { normal, insert }
|
||||
|
||||
class KeyboardNavigation extends StatefulWidget {
|
||||
const KeyboardNavigation({super.key, required this.child});
|
||||
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
State<KeyboardNavigation> createState() => _KeyboardNavigationState();
|
||||
}
|
||||
|
||||
class _KeyboardNavigationState extends State<KeyboardNavigation> {
|
||||
VimMode _mode = VimMode.normal;
|
||||
final FocusScopeNode _focusScopeNode = FocusScopeNode();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusScopeNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
KeyEventResult _handleKeyEvent(FocusNode node, KeyEvent event) {
|
||||
if (event is! KeyDownEvent && event is! KeyRepeatEvent) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
if (_mode == VimMode.normal) {
|
||||
if (event.logicalKey == LogicalKeyboardKey.keyJ) {
|
||||
node.focusInDirection(TraversalDirection.down);
|
||||
return KeyEventResult.handled;
|
||||
} else if (event.logicalKey == LogicalKeyboardKey.keyK) {
|
||||
node.focusInDirection(TraversalDirection.up);
|
||||
return KeyEventResult.handled;
|
||||
} else if (event.logicalKey == LogicalKeyboardKey.keyH) {
|
||||
final focusNode = FocusManager.instance.primaryFocus;
|
||||
if (focusNode != null) {
|
||||
final scrollable = Scrollable.of(focusNode.context!);
|
||||
if (scrollable.position.axis == Axis.horizontal) {
|
||||
scrollable.position.moveTo(scrollable.position.pixels - 50);
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
}
|
||||
node.focusInDirection(TraversalDirection.left);
|
||||
return KeyEventResult.handled;
|
||||
} else if (event.logicalKey == LogicalKeyboardKey.keyL) {
|
||||
final focusNode = FocusManager.instance.primaryFocus;
|
||||
if (focusNode != null) {
|
||||
final scrollable = Scrollable.of(focusNode.context!);
|
||||
if (scrollable.position.axis == Axis.horizontal) {
|
||||
scrollable.position.moveTo(scrollable.position.pixels + 50);
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
}
|
||||
node.focusInDirection(TraversalDirection.right);
|
||||
return KeyEventResult.handled;
|
||||
} else if (event.logicalKey == LogicalKeyboardKey.keyI) {
|
||||
setState(() {
|
||||
_mode = VimMode.insert;
|
||||
});
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
} else if (_mode == VimMode.insert) {
|
||||
if (event.logicalKey == LogicalKeyboardKey.escape) {
|
||||
setState(() {
|
||||
_mode = VimMode.normal;
|
||||
});
|
||||
// Unfocus the current widget to prevent typing
|
||||
node.unfocus();
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
}
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Focus(
|
||||
focusNode: _focusScopeNode,
|
||||
onKeyEvent: _handleKeyEvent,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user