work
@ -46,7 +46,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "com.vekoni.veilidchat.veilidchat"
|
||||
applicationId "com.veilid.veilidchat"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
||||
minSdkVersion Math.max(flutter.minSdkVersion, 24)
|
||||
|
@ -1,7 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.vekoni.veilidchat.veilidchat">
|
||||
package="com.veilid.veilidchat">
|
||||
<application
|
||||
android:label="veilidchat"
|
||||
android:label="VeilidChat"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
|
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 28 KiB |
@ -1,7 +1,21 @@
|
||||
{
|
||||
"app_bar": {
|
||||
"app": {
|
||||
"title": "VeilidChat"
|
||||
},
|
||||
"app_bar": {
|
||||
"settings_tooltip": "Settings"
|
||||
},
|
||||
"new_account_page": {
|
||||
"title": "Create a new account",
|
||||
"header": "Account Profile",
|
||||
"import": "Import an existing account"
|
||||
},
|
||||
"new_account_form": {
|
||||
"name": "Name",
|
||||
"title": "Title (optional)",
|
||||
"create": "Create",
|
||||
"instructions": "This information will be shared with the people you invite to connect with you on VeilidChat."
|
||||
},
|
||||
"button": {
|
||||
"cancel": "Cancel",
|
||||
"change_language": "Change Language"
|
||||
|
50
assets/images/vlogo.svg
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
assets/launcher/icon.png
Normal file
After Width: | Height: | Size: 260 KiB |
BIN
assets/sources/vlogo.afdesign
Normal file
@ -1,34 +1,57 @@
|
||||
PODS:
|
||||
- Flutter (1.0.0)
|
||||
- path_provider_ios (0.0.1):
|
||||
- FMDB (2.7.5):
|
||||
- FMDB/standard (= 2.7.5)
|
||||
- FMDB/standard (2.7.5)
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences_ios (0.0.1):
|
||||
- FlutterMacOS
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqflite (0.0.3):
|
||||
- Flutter
|
||||
- FMDB (>= 2.7.5)
|
||||
- system_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- veilid (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- Flutter (from `Flutter`)
|
||||
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
||||
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||
- system_info_plus (from `.symlinks/plugins/system_info_plus/ios`)
|
||||
- veilid (from `.symlinks/plugins/veilid/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- FMDB
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
path_provider_ios:
|
||||
:path: ".symlinks/plugins/path_provider_ios/ios"
|
||||
shared_preferences_ios:
|
||||
:path: ".symlinks/plugins/shared_preferences_ios/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
sqflite:
|
||||
:path: ".symlinks/plugins/sqflite/ios"
|
||||
system_info_plus:
|
||||
:path: ".symlinks/plugins/system_info_plus/ios"
|
||||
veilid:
|
||||
:path: ".symlinks/plugins/veilid/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
||||
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
|
||||
system_info_plus: 5393c8da281d899950d751713575fbf91c7709aa
|
||||
veilid: f5c2e662f91907b30cf95762619526ac3e4512fd
|
||||
|
||||
PODFILE CHECKSUM: fcab1959fbc0528061dce4ed4f921740dc46f1e5
|
||||
|
||||
COCOAPODS: 1.11.3
|
||||
COCOAPODS: 1.12.1
|
||||
|
@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@ -216,10 +216,12 @@
|
||||
};
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
@ -230,6 +232,7 @@
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 246 KiB |
Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 20 KiB |
@ -27,7 +27,7 @@ class VeilidChatApp extends ConsumerWidget {
|
||||
child: MaterialApp.router(
|
||||
debugShowCheckedModeBanner: false,
|
||||
routerConfig: router,
|
||||
title: 'VeilidChat',
|
||||
title: translate("app.title"),
|
||||
theme: theme,
|
||||
localizationsDelegates: [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
|
@ -1,10 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'package:circular_profile_avatar/circular_profile_avatar.dart';
|
||||
import 'package:badges/badges.dart';
|
||||
import 'package:awesome_extensions/awesome_extensions.dart';
|
||||
|
||||
import '../entities/local_account.dart';
|
||||
import '../providers/logins.dart';
|
||||
@ -30,3 +30,22 @@ class AccountBubble extends ConsumerWidget {
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
class AddAccountBubble extends ConsumerWidget {
|
||||
const AddAccountBubble({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
windowManager.setTitleBarStyle(TitleBarStyle.normal);
|
||||
final logins = ref.watch(loginsProvider);
|
||||
|
||||
return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
CircularProfileAvatar("",
|
||||
borderWidth: 4,
|
||||
borderColor: Theme.of(context).unselectedWidgetColor,
|
||||
child: Container(
|
||||
color: Colors.blue, child: const Icon(Icons.add, size: 50))),
|
||||
const Text("Add Account").paddingLTRB(0, 4, 0, 0)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class ChatPage extends ConsumerWidget {
|
||||
const ChatPage({super.key});
|
||||
static const path = '/chat';
|
||||
class Chat extends ConsumerWidget {
|
||||
const Chat({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
@ -1,9 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class ContactsPage extends ConsumerWidget {
|
||||
const ContactsPage({super.key});
|
||||
static const path = '/contacts';
|
||||
class ChatIndex extends ConsumerWidget {
|
||||
const ChatIndex({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
29
lib/components/default_app_bar.dart
Normal file
@ -0,0 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:flutter_translate/flutter_translate.dart';
|
||||
|
||||
class DefaultAppBar extends AppBar {
|
||||
DefaultAppBar(BuildContext context,
|
||||
{super.key, required super.title, Widget? leading, List<Widget>? actions})
|
||||
: super(
|
||||
leading: leading ??
|
||||
Container(
|
||||
margin: const EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withAlpha(32),
|
||||
shape: BoxShape.circle),
|
||||
child: SvgPicture.asset("assets/images/vlogo.svg",
|
||||
height: 48)),
|
||||
actions: (actions ?? <Widget>[])
|
||||
..add(
|
||||
IconButton(
|
||||
icon: const Icon(Icons.settings),
|
||||
tooltip: translate('app_bar.settings_tooltip'),
|
||||
onPressed: () {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||
content: Text(
|
||||
'Accessibility and language options coming soon')));
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
71
lib/components/new_account_form.dart
Normal file
@ -0,0 +1,71 @@
|
||||
import 'package:awesome_extensions/awesome_extensions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_translate/flutter_translate.dart';
|
||||
|
||||
import '../components/default_app_bar.dart';
|
||||
import '../tools/desktop_control.dart';
|
||||
|
||||
class NewAccountForm extends ConsumerStatefulWidget {
|
||||
const NewAccountForm({super.key});
|
||||
|
||||
@override
|
||||
NewAccountFormState createState() {
|
||||
return NewAccountFormState();
|
||||
}
|
||||
}
|
||||
|
||||
class NewAccountFormState extends ConsumerState<NewAccountForm> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
key: const ValueKey("name"),
|
||||
autofocus: true,
|
||||
decoration:
|
||||
InputDecoration(hintText: translate("new_account_form.name")),
|
||||
maxLength: 64,
|
||||
// The validator receives the text that the user has entered.
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Name is required';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
key: const ValueKey("title"),
|
||||
maxLength: 64,
|
||||
decoration:
|
||||
InputDecoration(hintText: translate("new_account_form.title")),
|
||||
),
|
||||
Row(children: [
|
||||
const Spacer(),
|
||||
Text(translate("new_account_form.instructions"))
|
||||
.toCenter()
|
||||
.flexible(flex: 4),
|
||||
const Spacer(),
|
||||
]).paddingSymmetric(vertical: 24),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
// Validate returns true if the form is valid, or false otherwise.
|
||||
if (_formKey.currentState!.validate()) {
|
||||
// If the form is valid, display a snackbar. In the real world,
|
||||
// you'd often call a server or save the information in a database.
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Processing Data')),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(translate('new_account_form.create')),
|
||||
).paddingSymmetric(vertical: 16).toCenter(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_translate/flutter_translate.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import 'log/log.dart';
|
||||
import 'veilid_support/veilid_support.dart';
|
||||
@ -12,6 +11,8 @@ import 'theming/theming.dart';
|
||||
import 'app.dart';
|
||||
import 'dart:io';
|
||||
|
||||
import '../tools/desktop_control.dart';
|
||||
|
||||
void main() async {
|
||||
// Disable all debugprints in release mode
|
||||
if (kReleaseMode) {
|
||||
@ -32,21 +33,7 @@ void main() async {
|
||||
var initTheme = themeService.initial;
|
||||
|
||||
// Manage window on desktop platforms
|
||||
if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
|
||||
await windowManager.ensureInitialized();
|
||||
|
||||
const windowOptions = WindowOptions(
|
||||
size: Size(768, 1024),
|
||||
center: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
skipTaskbar: false,
|
||||
titleBarStyle: TitleBarStyle.hidden,
|
||||
);
|
||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
});
|
||||
}
|
||||
await setupDesktopWindow();
|
||||
|
||||
// Make localization delegate
|
||||
var delegate = await LocalizationDelegate.create(
|
||||
|
@ -1,7 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:radix_colors/radix_colors.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import '../tools/desktop_control.dart';
|
||||
|
||||
class IndexPage extends StatelessWidget {
|
||||
const IndexPage({super.key});
|
||||
@ -9,7 +10,7 @@ class IndexPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
windowManager.setTitleBarStyle(TitleBarStyle.hidden);
|
||||
enableTitleBar(false);
|
||||
return Scaffold(
|
||||
body: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
|
@ -39,27 +39,30 @@ class LoginPage extends ConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
body: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Spacer(),
|
||||
accounts.when(
|
||||
error: (obj, err) => Text("error loading accounts: $err"),
|
||||
loading: () => CircularProgressIndicator(),
|
||||
data: (accountList) => ReorderableGridView.extent(
|
||||
maxCrossAxisExtent: 128,
|
||||
onReorder: (oldIndex, newIndex) =>
|
||||
_onReorder(ref, oldIndex, newIndex),
|
||||
children: accountList.map((account) {
|
||||
return AccountBubble(account: account);
|
||||
}).toList(),
|
||||
)),
|
||||
const Spacer(),
|
||||
Container(height: 100, color: Color.fromARGB(255, 255, 0, 0)),
|
||||
Spacer(),
|
||||
// accounts.when(
|
||||
// error: (obj, err) => Text("error loading accounts: $err"),
|
||||
// loading: () => CircularProgressIndicator(),
|
||||
// data: (accountList) => ReorderableGridView.extent(
|
||||
// maxCrossAxisExtent: 128,
|
||||
// onReorder: (oldIndex, newIndex) =>
|
||||
// _onReorder(ref, oldIndex, newIndex),
|
||||
// children: accountList.map<Widget>((account) {
|
||||
// return AccountBubble(
|
||||
// key: ValueKey(account.identityMaster.masterRecordKey),
|
||||
// account: account);
|
||||
// }).toList(),
|
||||
// )),
|
||||
AddAccountBubble(key: ValueKey("+")),
|
||||
Spacer(),
|
||||
Container(height: 100, color: Color.fromARGB(255, 0, 255, 0)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,11 @@
|
||||
import 'package:awesome_extensions/awesome_extensions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_translate/flutter_translate.dart';
|
||||
|
||||
import '../components/default_app_bar.dart';
|
||||
import '../components/new_account_form.dart';
|
||||
import '../tools/tools.dart';
|
||||
|
||||
class NewAccountPage extends ConsumerWidget {
|
||||
const NewAccountPage({super.key});
|
||||
@ -7,26 +13,25 @@ class NewAccountPage extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
enableTitleBar(true);
|
||||
|
||||
return Scaffold(
|
||||
appBar: null,
|
||||
body: Center(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: DefaultAppBar(context,
|
||||
title: Text(translate("new_account_page.title"))),
|
||||
body: Container(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Text("New Account Page"),
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// ref.watch(authNotifierProvider.notifier).login(
|
||||
// "myEmail",
|
||||
// "myPassword",
|
||||
// );
|
||||
// },
|
||||
// child: const Text("Login"),
|
||||
// ),
|
||||
Text(translate("new_account_page.header"))
|
||||
.textStyle(context.headlineSmall)
|
||||
.paddingSymmetric(vertical: 16),
|
||||
const NewAccountForm().flexible(),
|
||||
Text(translate("new_account_page.import"))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ part of 'local_accounts.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$localAccountsHash() => r'694236fa91156c00b3f7d6985fbc55b8871646ab';
|
||||
String _$localAccountsHash() => r'1faa6b22284a402e4f47b2629e54a39ffda9a4ad';
|
||||
|
||||
/// See also [LocalAccounts].
|
||||
@ProviderFor(LocalAccounts)
|
||||
|
@ -5,12 +5,14 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import '../pages/pages.dart';
|
||||
import 'router_notifier.dart';
|
||||
|
||||
part 'router.g.dart';
|
||||
|
||||
final _key = GlobalKey<NavigatorState>(debugLabel: 'routerKey');
|
||||
|
||||
/// This simple provider caches our GoRouter.
|
||||
final routerProvider = Provider.autoDispose<GoRouter>((ref) {
|
||||
@riverpod
|
||||
GoRouter router(RouterRef ref) {
|
||||
final notifier = ref.watch(routerNotifierProvider.notifier);
|
||||
|
||||
return GoRouter(
|
||||
navigatorKey: _key,
|
||||
refreshListenable: notifier,
|
||||
@ -19,4 +21,4 @@ final routerProvider = Provider.autoDispose<GoRouter>((ref) {
|
||||
routes: notifier.routes,
|
||||
redirect: notifier.redirect,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
25
lib/router/router.g.dart
Normal file
@ -0,0 +1,25 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'router.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$routerHash() => r'2273f69a347c52bbb53358ac9034ab0ea760ecce';
|
||||
|
||||
/// This simple provider caches our GoRouter.
|
||||
///
|
||||
/// Copied from [router].
|
||||
@ProviderFor(router)
|
||||
final routerProvider = AutoDisposeProvider<GoRouter>.internal(
|
||||
router,
|
||||
name: r'routerProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : _$routerHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef RouterRef = AutoDisposeProviderRef<GoRouter>;
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
@ -1,23 +1,25 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
import '../pages/pages.dart';
|
||||
import '../providers/logins.dart';
|
||||
import '../providers/local_accounts.dart';
|
||||
|
||||
class RouterNotifier extends AutoDisposeAsyncNotifier<void>
|
||||
implements Listenable {
|
||||
part 'router_notifier.g.dart';
|
||||
|
||||
@riverpod
|
||||
class RouterNotifier extends _$RouterNotifier implements Listenable {
|
||||
/// GoRouter listener
|
||||
VoidCallback? routerListener;
|
||||
|
||||
/// Router state for redirect
|
||||
bool hasActiveUserLogin = false;
|
||||
/// Do we need to make or import an account immediately?
|
||||
bool hasAnyAccount = false;
|
||||
|
||||
/// AsyncNotifier build
|
||||
@override
|
||||
Future<void> build() async {
|
||||
hasActiveUserLogin = await ref.watch(
|
||||
loginsProvider.selectAsync((data) => data.activeUserLogin != null),
|
||||
hasAnyAccount = await ref.watch(
|
||||
localAccountsProvider.selectAsync((data) => data.isNotEmpty),
|
||||
);
|
||||
|
||||
// When this notifier's state changes, inform GoRouter
|
||||
@ -33,11 +35,9 @@ class RouterNotifier extends AutoDisposeAsyncNotifier<void>
|
||||
|
||||
switch (state.location) {
|
||||
case IndexPage.path:
|
||||
return hasActiveUserLogin ? HomePage.path : LoginPage.path;
|
||||
case LoginPage.path:
|
||||
return hasActiveUserLogin ? HomePage.path : null;
|
||||
return hasAnyAccount ? HomePage.path : NewAccountPage.path;
|
||||
default:
|
||||
return hasActiveUserLogin ? null : LoginPage.path;
|
||||
return hasAnyAccount ? null : NewAccountPage.path;
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,38 +50,6 @@ class RouterNotifier extends AutoDisposeAsyncNotifier<void>
|
||||
GoRoute(
|
||||
path: HomePage.path,
|
||||
builder: (context, state) => const HomePage(),
|
||||
// redirect: (context, state) async {
|
||||
// if (state.location == HomePage.path) return null;
|
||||
|
||||
// // final roleListener = ProviderScope.containerOf(context).listen(
|
||||
// // permissionsProvider.select((value) => value.valueOrNull),
|
||||
// // (previous, next) {},
|
||||
// // );
|
||||
|
||||
// // final userRole = roleListener.read();
|
||||
// // final redirectTo = userRole?.redirectBasedOn(state.location);
|
||||
|
||||
// // roleListener.close();
|
||||
// // return redirectTo;
|
||||
// },
|
||||
// routes: [
|
||||
// GoRoute(
|
||||
// path: AdminPage.path,
|
||||
// builder: (context, state) => const AdminPage(),
|
||||
// ),
|
||||
// GoRoute(
|
||||
// path: UserPage.path,
|
||||
// builder: (context, state) => const UserPage(),
|
||||
// ),
|
||||
// GoRoute(
|
||||
// path: GuestPage.path,
|
||||
// builder: (context, state) => const GuestPage(),
|
||||
// )
|
||||
// ]
|
||||
),
|
||||
GoRoute(
|
||||
path: LoginPage.path,
|
||||
builder: (context, state) => const LoginPage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: NewAccountPage.path,
|
||||
@ -112,27 +80,3 @@ class RouterNotifier extends AutoDisposeAsyncNotifier<void>
|
||||
routerListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
final routerNotifierProvider =
|
||||
AutoDisposeAsyncNotifierProvider<RouterNotifier, void>(() {
|
||||
return RouterNotifier();
|
||||
});
|
||||
|
||||
/// A simple extension to determine wherever should we redirect our users
|
||||
// extension RedirecttionBasedOnRole on UserRole {
|
||||
// /// Redirects the users based on [this] and its current [location]
|
||||
// String? redirectBasedOn(String location) {
|
||||
// switch (this) {
|
||||
// case UserRole.admin:
|
||||
// return null;
|
||||
// case UserRole.verifiedUser:
|
||||
// case UserRole.unverifiedUser:
|
||||
// if (location == AdminPage.path) return HomePage.path;
|
||||
// return null;
|
||||
// case UserRole.guest:
|
||||
// case UserRole.none:
|
||||
// if (location != HomePage.path) return HomePage.path;
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
25
lib/router/router_notifier.g.dart
Normal file
@ -0,0 +1,25 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'router_notifier.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$routerNotifierHash() => r'00de1dd715945e96b49507ea55d7b97a78366adc';
|
||||
|
||||
/// See also [RouterNotifier].
|
||||
@ProviderFor(RouterNotifier)
|
||||
final routerNotifierProvider =
|
||||
AutoDisposeAsyncNotifierProvider<RouterNotifier, void>.internal(
|
||||
RouterNotifier.new,
|
||||
name: r'routerNotifierProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$routerNotifierHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$RouterNotifier = AutoDisposeAsyncNotifier<void>;
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
32
lib/tools/desktop_control.dart
Normal file
@ -0,0 +1,32 @@
|
||||
import 'dart:io';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Future<void> setupDesktopWindow() async {
|
||||
if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
|
||||
await windowManager.ensureInitialized();
|
||||
|
||||
const windowOptions = WindowOptions(
|
||||
size: Size(768, 1024),
|
||||
minimumSize: Size(480, 640),
|
||||
center: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
skipTaskbar: false,
|
||||
titleBarStyle: TitleBarStyle.hidden,
|
||||
);
|
||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void enableTitleBar(bool enabled) {
|
||||
if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
|
||||
if (enabled) {
|
||||
windowManager.setTitleBarStyle(TitleBarStyle.normal);
|
||||
} else {
|
||||
windowManager.setTitleBarStyle(TitleBarStyle.hidden);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,3 +2,5 @@ export 'external_stream_state.dart';
|
||||
export 'json_tools.dart';
|
||||
export 'phono_byte.dart';
|
||||
export 'protobuf_tools.dart';
|
||||
export 'widget_helpers.dart';
|
||||
export 'desktop_control.dart';
|
||||
|
9
lib/tools/widget_helpers.dart
Normal file
@ -0,0 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
extension BorderExt on Widget {
|
||||
Container debugBorder() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(border: Border.all(color: Colors.redAccent)),
|
||||
child: this);
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ void _initVeilid() {
|
||||
otlp: VeilidFFIConfigLoggingOtlp(
|
||||
enabled: false,
|
||||
level: VeilidConfigLogLevel.trace,
|
||||
grpcEndpoint: "localhost:4317",
|
||||
grpcEndpoint: "192.168.1.40:4317",
|
||||
serviceName: "VeilidChat"),
|
||||
api: VeilidFFIConfigLoggingApi(
|
||||
enabled: true, level: VeilidConfigLogLevel.info)));
|
||||
|
@ -1,4 +1,8 @@
|
||||
{
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"size": "16x16",
|
||||
@ -60,9 +64,5 @@
|
||||
"filename": "app_icon_1024.png",
|
||||
"scale": "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
]
|
||||
}
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 268 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 520 B After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 6.8 KiB |
48
pubspec.lock
@ -41,6 +41,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.7"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -57,6 +65,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
awesome_extensions:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: awesome_extensions
|
||||
sha256: "6b9c6a5f70d17959ace71d649d3b816b13b73267196035d431ff17e65a228608"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.9"
|
||||
badges:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -374,6 +390,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.18.6"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_launcher_icons
|
||||
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.1"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@ -509,6 +533,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.17"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -709,6 +741,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.7.3"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -978,6 +1018,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
system_info_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: system_info_plus
|
||||
sha256: b915c811c6605b802f3988859bc2bb79c95f735762a75b5451741f7a2b949d1b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.0.5"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
23
pubspec.yaml
@ -44,6 +44,7 @@ dependencies:
|
||||
reorderable_grid: ^1.0.7
|
||||
circular_profile_avatar: ^2.0.5
|
||||
badges: ^3.1.1
|
||||
awesome_extensions: ^2.0.9
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
@ -53,14 +54,36 @@ dev_dependencies:
|
||||
freezed: ^2.3.5
|
||||
json_serializable: ^6.7.1
|
||||
riverpod_generator: ^2.2.3
|
||||
flutter_launcher_icons: "^0.13.1"
|
||||
|
||||
flutter_launcher_icons:
|
||||
image_path: "assets/launcher/icon.png"
|
||||
android: true
|
||||
ios: true
|
||||
remove_alpha_ios: true
|
||||
min_sdk_android: 24 # android min sdk min:16, default 21
|
||||
web:
|
||||
generate: true
|
||||
background_color: "#33183f"
|
||||
theme_color: "#863fa6"
|
||||
windows:
|
||||
generate: true
|
||||
icon_size: 48 # min:48, max:256, default: 48
|
||||
macos:
|
||||
generate: true
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
assets:
|
||||
# Translations
|
||||
- assets/i18n/en.json
|
||||
# Launcher icon
|
||||
- assets/launcher/icon.png
|
||||
# Images
|
||||
- assets/images/splash.svg
|
||||
- assets/images/icon.svg
|
||||
- assets/images/title.svg
|
||||
- assets/images/vlogo.svg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
2
update_icons.sh
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
dart run flutter_launcher_icons
|
BIN
web/favicon.png
Before Width: | Height: | Size: 917 B After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 95 KiB |
@ -3,8 +3,8 @@
|
||||
"short_name": "veilidchat",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"background_color": "#0175C2",
|
||||
"theme_color": "#0175C2",
|
||||
"background_color": "#33183f",
|
||||
"theme_color": "#863fa6",
|
||||
"description": "VeilidChat",
|
||||
"orientation": "portrait-primary",
|
||||
"prefer_related_applications": false,
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 4.8 KiB |