Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
c0d14ac30e |
|||
|
1a6a5c36ea |
|||
|
35ef82accd |
|||
|
f40dd22277 |
|||
|
1cfea5a819 |
|||
|
b3023d8147 |
|||
|
e8fb3a8523 |
|||
|
0d1ace3fd0 |
|||
|
3d690c26d8 |
19 changed files with 215 additions and 112 deletions
17
.vscode/launch.json
vendored
Normal file
17
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Flutter",
|
||||||
|
"type": "dart",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "lib/main.dart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Flutter (Headless)",
|
||||||
|
"type": "dart",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "lib/main.dart",
|
||||||
|
"env": { "FLUTTER_HEADLESS": "1" }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -127,6 +127,7 @@ If you want to try out Nexus, grab one of the following artifacts from CI:
|
||||||
- Flatpak
|
- Flatpak
|
||||||
- [AArch64/Arm64](https://nightly.link/Henry-Hiles/nexus/workflows/flatpak/main/flatpak-aarch64.zip)
|
- [AArch64/Arm64](https://nightly.link/Henry-Hiles/nexus/workflows/flatpak/main/flatpak-aarch64.zip)
|
||||||
- [x86_64/AMD64](https://nightly.link/Henry-Hiles/nexus/workflows/flatpak/main/flatpak-x86_64.zip)
|
- [x86_64/AMD64](https://nightly.link/Henry-Hiles/nexus/workflows/flatpak/main/flatpak-x86_64.zip)
|
||||||
|
- [NixOS Module](linux/nix/module.nix)
|
||||||
|
|
||||||
## Build it yourself
|
## Build it yourself
|
||||||
|
|
||||||
|
|
|
||||||
57
flake.nix
57
flake.nix
|
|
@ -16,67 +16,12 @@
|
||||||
...
|
...
|
||||||
}@inputs:
|
}@inputs:
|
||||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||||
|
imports = [ ./linux/nix ];
|
||||||
systems = [
|
systems = [
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
"aarch64-linux"
|
"aarch64-linux"
|
||||||
"aarch64-darwin"
|
"aarch64-darwin"
|
||||||
"x86_64-darwin"
|
"x86_64-darwin"
|
||||||
];
|
];
|
||||||
|
|
||||||
perSystem =
|
|
||||||
{
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
system,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
{
|
|
||||||
_module.args.pkgs = import nixpkgs {
|
|
||||||
inherit system;
|
|
||||||
config = {
|
|
||||||
android_sdk.accept_license = true;
|
|
||||||
allowUnfree = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
packages =
|
|
||||||
let
|
|
||||||
default = pkgs.callPackage ./linux/nix/pkg {
|
|
||||||
src = self;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
inherit default;
|
|
||||||
|
|
||||||
flatpak = inputs.nix2flatpak.lib.${system}.mkFlatpak {
|
|
||||||
appName = "Nexus";
|
|
||||||
developer = "QuadRadical";
|
|
||||||
appId = "nexus.federated.nexus";
|
|
||||||
package = default;
|
|
||||||
runtime = "org.gnome.Platform/49";
|
|
||||||
permissions = {
|
|
||||||
share = [ "network" ];
|
|
||||||
sockets = [
|
|
||||||
"pulseaudio"
|
|
||||||
"fallback-x11"
|
|
||||||
"wayland"
|
|
||||||
];
|
|
||||||
|
|
||||||
talk-names = [
|
|
||||||
"org.unifiedpush.Distributor.*"
|
|
||||||
"org.freedesktop.Notifications"
|
|
||||||
];
|
|
||||||
devices = [ "dri" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
gomuks = pkgs.callPackage ./linux/nix/pkg/gomuks.nix {
|
|
||||||
src = self;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
devShells.default = pkgs.callPackage ./linux/nix/devshell.nix { };
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/shared_prefs.dart";
|
import "package:nexus/controllers/shared_prefs.dart";
|
||||||
|
|
||||||
class KeyController(final String key) extends Notifier<String?> {
|
class KeyController(final String key) extends AsyncNotifier<String?> {
|
||||||
static const String spaceKey = "space";
|
static const String spaceKey = "space";
|
||||||
static const String roomKey = "room";
|
static const String roomKey = "room";
|
||||||
static const String pushKeyKey = "pushKey";
|
static const String pushKeyKey = "pushKey";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? build() =>
|
Future<String?> build() =>
|
||||||
ref.watch(SharedPrefsController.provider).requireValue.getString(key);
|
ref.watch(SharedPrefsController.provider).getString(key);
|
||||||
|
|
||||||
Future<void> set(String? value) async {
|
Future<void> set(String? value) async {
|
||||||
final prefs = ref.watch(SharedPrefsController.provider).requireValue;
|
final prefs = ref.watch(SharedPrefsController.provider);
|
||||||
state = value;
|
state = .data(value);
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
prefs.remove(key);
|
await prefs.remove(key);
|
||||||
} else {
|
} else {
|
||||||
prefs.setString(key, value);
|
await prefs.setString(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final provider =
|
static final provider =
|
||||||
NotifierProvider.family<KeyController, String?, String>(
|
AsyncNotifierProvider.family<KeyController, String?, String>(
|
||||||
KeyController.new,
|
KeyController.new,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/shared_prefs.dart";
|
import "package:nexus/controllers/shared_prefs.dart";
|
||||||
|
|
||||||
class MemberListOpenedController extends Notifier<bool> {
|
class MemberListOpenedController extends AsyncNotifier<bool> {
|
||||||
static const String key = "memberListOpened";
|
static const String key = "memberListOpened";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool build() =>
|
Future<bool> build() async =>
|
||||||
ref.watch(SharedPrefsController.provider).requireValue.getBool(key) ??
|
await ref.watch(SharedPrefsController.provider).getBool(key) ?? true;
|
||||||
true;
|
|
||||||
|
|
||||||
Future<void> set(bool value) async {
|
Future<void> set(bool value) async {
|
||||||
final prefs = ref.watch(SharedPrefsController.provider).requireValue;
|
state = .data(value);
|
||||||
state = value;
|
await ref.watch(SharedPrefsController.provider).setBool(key, value);
|
||||||
|
|
||||||
prefs.setBool(key, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static final provider = NotifierProvider<MemberListOpenedController, bool>(
|
static final provider =
|
||||||
MemberListOpenedController.new,
|
AsyncNotifierProvider<MemberListOpenedController, bool>(
|
||||||
);
|
MemberListOpenedController.new,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ class NotificationController
|
||||||
File? icon,
|
File? icon,
|
||||||
String? payload,
|
String? payload,
|
||||||
}) async {
|
}) async {
|
||||||
|
debugPrint("Sending notification for $id");
|
||||||
final notificationDetails = NotificationDetails(
|
final notificationDetails = NotificationDetails(
|
||||||
android: .new(
|
android: .new(
|
||||||
"messages",
|
"messages",
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,19 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/key.dart";
|
import "package:nexus/controllers/key.dart";
|
||||||
|
|
||||||
class PushKeyController(final String instance) extends Notifier<String?> {
|
class PushKeyController(final String instance) extends AsyncNotifier<String?> {
|
||||||
@override
|
@override
|
||||||
String? build() => json.decode(
|
Future<String?> build() async => json.decode(
|
||||||
ref.watch(KeyController.provider(KeyController.pushKeyKey)) ?? "{}",
|
await ref.watch(KeyController.provider(KeyController.pushKeyKey).future) ??
|
||||||
|
"{}",
|
||||||
)[instance];
|
)[instance];
|
||||||
|
|
||||||
Future<void> set(String? value) async {
|
Future<void> set(String? value) async {
|
||||||
final provider = KeyController.provider(KeyController.pushKeyKey);
|
final provider = KeyController.provider(KeyController.pushKeyKey);
|
||||||
final notifier = ref.watch(provider.notifier);
|
final notifier = ref.watch(provider.notifier);
|
||||||
final prefs = IMap(json.decode(ref.watch(provider) ?? "{}"));
|
final prefs = IMap(json.decode(await ref.watch(provider.future) ?? "{}"));
|
||||||
|
|
||||||
state = value;
|
state = .data(value);
|
||||||
notifier.set(
|
notifier.set(
|
||||||
json.encode(
|
json.encode(
|
||||||
prefs.add(instance, value).where((_, value) => value != null).unlock,
|
prefs.add(instance, value).where((_, value) => value != null).unlock,
|
||||||
|
|
@ -24,7 +25,7 @@ class PushKeyController(final String instance) extends Notifier<String?> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static final provider =
|
static final provider =
|
||||||
NotifierProvider.family<PushKeyController, String?, String>(
|
AsyncNotifierProvider.family<PushKeyController, String?, String>(
|
||||||
PushKeyController.new,
|
PushKeyController.new,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:shared_preferences/shared_preferences.dart";
|
import "package:shared_preferences/shared_preferences.dart";
|
||||||
|
|
||||||
class SharedPrefsController extends AsyncNotifier<SharedPreferences> {
|
class SharedPrefsController extends Notifier<SharedPreferencesAsync> {
|
||||||
@override
|
@override
|
||||||
Future<SharedPreferences> build() async => .getInstance();
|
SharedPreferencesAsync build() => SharedPreferencesAsync();
|
||||||
|
|
||||||
static final provider =
|
static final provider =
|
||||||
AsyncNotifierProvider<SharedPrefsController, SharedPreferences>(
|
NotifierProvider<SharedPrefsController, SharedPreferencesAsync>(
|
||||||
SharedPrefsController.new,
|
SharedPrefsController.new,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import "package:nexus/controllers/client.dart";
|
||||||
import "package:nexus/controllers/client_state.dart";
|
import "package:nexus/controllers/client_state.dart";
|
||||||
import "package:nexus/models/content/message.dart";
|
import "package:nexus/models/content/message.dart";
|
||||||
import "package:nexus/models/content/sticker.dart";
|
import "package:nexus/models/content/sticker.dart";
|
||||||
import "package:nexus/models/requests/register_pusher.dart";
|
|
||||||
import "package:unifiedpush/unifiedpush.dart";
|
import "package:unifiedpush/unifiedpush.dart";
|
||||||
import "package:unifiedpush_storage_shared_preferences/storage.dart";
|
import "package:unifiedpush_storage_shared_preferences/storage.dart";
|
||||||
import "package:window_manager/window_manager.dart";
|
import "package:window_manager/window_manager.dart";
|
||||||
|
|
@ -29,6 +28,7 @@ class UnifiedPushController extends AsyncNotifier<bool> {
|
||||||
dbusName: "nexus.federated.nexus.UnifiedPush",
|
dbusName: "nexus.federated.nexus.UnifiedPush",
|
||||||
storage: UnifiedPushStorageSharedPreferences(),
|
storage: UnifiedPushStorageSharedPreferences(),
|
||||||
background: isInBackground,
|
background: isInBackground,
|
||||||
|
shouldWriteService: false,
|
||||||
),
|
),
|
||||||
onNewEndpoint: (endpoint, instance) async {
|
onNewEndpoint: (endpoint, instance) async {
|
||||||
final pushKey = endpoint.pubKeySet!.pubKey;
|
final pushKey = endpoint.pubKeySet!.pubKey;
|
||||||
|
|
@ -40,8 +40,8 @@ class UnifiedPushController extends AsyncNotifier<bool> {
|
||||||
.new(
|
.new(
|
||||||
appDisplayName: "Nexus",
|
appDisplayName: "Nexus",
|
||||||
appId: "nexus.federated.nexus",
|
appId: "nexus.federated.nexus",
|
||||||
data: PusherData.webPush(
|
data: .webPush(
|
||||||
url: Uri.parse(endpoint.url),
|
url: .parse(endpoint.url),
|
||||||
auth: endpoint.pubKeySet!.auth,
|
auth: endpoint.pubKeySet!.auth,
|
||||||
),
|
),
|
||||||
deviceDisplayName:
|
deviceDisplayName:
|
||||||
|
|
@ -53,6 +53,7 @@ class UnifiedPushController extends AsyncNotifier<bool> {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onMessage: (message, instance) async {
|
onMessage: (message, instance) async {
|
||||||
|
debugPrint("UP message received for $instance");
|
||||||
if (message.decrypted == false) {
|
if (message.decrypted == false) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"Failed to decrypt notification. Try toggling off and on UnifiedPush in settings.",
|
"Failed to decrypt notification. Try toggling off and on UnifiedPush in settings.",
|
||||||
|
|
@ -66,8 +67,11 @@ class UnifiedPushController extends AsyncNotifier<bool> {
|
||||||
event.unreadType?.shouldNotify() != true ||
|
event.unreadType?.shouldNotify() != true ||
|
||||||
(!isInBackground &&
|
(!isInBackground &&
|
||||||
await windowManager.isFocused().onError((_, _) => false) &&
|
await windowManager.isFocused().onError((_, _) => false) &&
|
||||||
ref.watch(KeyController.provider(KeyController.roomKey)) ==
|
await ref.watch(
|
||||||
|
KeyController.provider(KeyController.roomKey).future,
|
||||||
|
) ==
|
||||||
event.roomId)) {
|
event.roomId)) {
|
||||||
|
if (isInBackground) exit(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,7 +148,9 @@ class UnifiedPushController extends AsyncNotifier<bool> {
|
||||||
|
|
||||||
Future<void> deregister() async {
|
Future<void> deregister() async {
|
||||||
final clientState = ref.watch(ClientStateController.provider);
|
final clientState = ref.watch(ClientStateController.provider);
|
||||||
final key = ref.watch(PushKeyController.provider(clientState!.deviceId!));
|
final key = await ref.watch(
|
||||||
|
PushKeyController.provider(clientState!.deviceId!).future,
|
||||||
|
);
|
||||||
|
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
await ref
|
await ref
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@ import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:media_kit/media_kit.dart";
|
import "package:media_kit/media_kit.dart";
|
||||||
import "package:nexus/controllers/client.dart";
|
import "package:nexus/controllers/client.dart";
|
||||||
import "package:nexus/controllers/client_state.dart";
|
import "package:nexus/controllers/client_state.dart";
|
||||||
|
import "package:nexus/controllers/key.dart";
|
||||||
|
import "package:nexus/controllers/member_list_opened.dart";
|
||||||
import "package:nexus/controllers/multi_provider.dart";
|
import "package:nexus/controllers/multi_provider.dart";
|
||||||
import "package:nexus/controllers/notification.dart";
|
import "package:nexus/controllers/notification.dart";
|
||||||
import "package:nexus/controllers/settings.dart";
|
import "package:nexus/controllers/settings.dart";
|
||||||
import "package:nexus/controllers/shared_prefs.dart";
|
|
||||||
import "package:nexus/controllers/unified_push.dart";
|
import "package:nexus/controllers/unified_push.dart";
|
||||||
import "package:nexus/helpers/extensions/better_when.dart";
|
import "package:nexus/helpers/extensions/better_when.dart";
|
||||||
import "package:nexus/helpers/extensions/scheme_to_theme.dart";
|
import "package:nexus/helpers/extensions/scheme_to_theme.dart";
|
||||||
|
|
@ -81,14 +82,20 @@ void main(List<String> args) async {
|
||||||
await windowManager.setMinimumSize(Size.square(500));
|
await windowManager.setMinimumSize(Size.square(500));
|
||||||
}
|
}
|
||||||
|
|
||||||
isInBackground = args.contains("--unifiedpush-bg");
|
isInBackground = Platform.environment["FLUTTER_HEADLESS"] != null;
|
||||||
|
|
||||||
LicenseRegistry.addLicense(() => Stream.fromIterable(fontLicenses));
|
LicenseRegistry.addLicense(() => .fromIterable(fontLicenses));
|
||||||
|
|
||||||
FlutterError.onError = (FlutterErrorDetails details) =>
|
FlutterError.onError = (FlutterErrorDetails details) =>
|
||||||
showError(details.exception.toString(), details.stack);
|
showError(details.exception.toString(), details.stack);
|
||||||
|
|
||||||
if (!isInBackground) {
|
if (isInBackground) {
|
||||||
|
await ProviderContainer().read(UnifiedPushController.provider.future);
|
||||||
|
|
||||||
|
// In case it didn't exit for some reason
|
||||||
|
await Future.delayed(Duration(seconds: 20));
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
runApp(
|
runApp(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
retry: (_, _) => null,
|
retry: (_, _) => null,
|
||||||
|
|
@ -97,14 +104,13 @@ void main(List<String> args) async {
|
||||||
// ignore: dead_code
|
// ignore: dead_code
|
||||||
if (false && kDebugMode) Logger(),
|
if (false && kDebugMode) Logger(),
|
||||||
],
|
],
|
||||||
child: App(isInBackground),
|
child: App(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class const App(final bool isInBackground, {super.key})
|
class const App({super.key}) extends StatelessWidget {
|
||||||
extends StatelessWidget {
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => DynamicColorBuilder(
|
Widget build(BuildContext context) => DynamicColorBuilder(
|
||||||
builder: (lightDynamic, darkDynamic) => Consumer(
|
builder: (lightDynamic, darkDynamic) => Consumer(
|
||||||
|
|
@ -145,10 +151,12 @@ class const App(final bool isInBackground, {super.key})
|
||||||
.watch(
|
.watch(
|
||||||
MultiProviderController.provider(
|
MultiProviderController.provider(
|
||||||
IListConst([
|
IListConst([
|
||||||
SharedPrefsController.provider,
|
|
||||||
ClientController.provider,
|
ClientController.provider,
|
||||||
NotificationController.provider,
|
NotificationController.provider,
|
||||||
UnifiedPushController.provider,
|
UnifiedPushController.provider,
|
||||||
|
MemberListOpenedController.provider,
|
||||||
|
KeyController.provider(KeyController.roomKey),
|
||||||
|
KeyController.provider(KeyController.spaceKey),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,9 @@ class const ChatPage({super.key}) extends ConsumerWidget {
|
||||||
final isDesktop = constraints.maxWidth > 650;
|
final isDesktop = constraints.maxWidth > 650;
|
||||||
final showMembersByDefault = constraints.maxWidth > 1000;
|
final showMembersByDefault = constraints.maxWidth > 1000;
|
||||||
final initComplete = ref.watch(InitCompleteController.provider);
|
final initComplete = ref.watch(InitCompleteController.provider);
|
||||||
final roomId = ref.watch(KeyController.provider(KeyController.roomKey));
|
final roomId = ref
|
||||||
|
.watch(KeyController.provider(KeyController.roomKey))
|
||||||
|
.requireValue;
|
||||||
|
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,9 @@ final class const RoomChat({
|
||||||
final composerSize = useState<double>(64);
|
final composerSize = useState<double>(64);
|
||||||
|
|
||||||
final userId = ref.watch(ClientStateController.provider)?.userId;
|
final userId = ref.watch(ClientStateController.provider)?.userId;
|
||||||
final memberListOpened = ref.watch(MemberListOpenedController.provider);
|
final memberListOpened = ref
|
||||||
|
.watch(MemberListOpenedController.provider)
|
||||||
|
.requireValue;
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
final nothing = Center(
|
final nothing = Center(
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,13 @@ class const Sidebar({required final bool isDesktop, super.key})
|
||||||
final selectedSpaceProvider = KeyController.provider(
|
final selectedSpaceProvider = KeyController.provider(
|
||||||
KeyController.spaceKey,
|
KeyController.spaceKey,
|
||||||
);
|
);
|
||||||
final selectedSpaceId = ref.watch(selectedSpaceProvider);
|
final selectedSpaceId = ref.watch(selectedSpaceProvider).requireValue;
|
||||||
final selectedSpaceIdNotifier = ref.watch(selectedSpaceProvider.notifier);
|
final selectedSpaceIdNotifier = ref.watch(selectedSpaceProvider.notifier);
|
||||||
|
|
||||||
final selectedRoomController = KeyController.provider(
|
final selectedRoomController = KeyController.provider(
|
||||||
KeyController.roomKey,
|
KeyController.roomKey,
|
||||||
);
|
);
|
||||||
final selectedRoomId = ref.watch(selectedRoomController);
|
final selectedRoomId = ref.watch(selectedRoomController).requireValue;
|
||||||
final selectedRoomIdNotifier = ref.watch(selectedRoomController.notifier);
|
final selectedRoomIdNotifier = ref.watch(selectedRoomController.notifier);
|
||||||
|
|
||||||
final spaces = ref.watch(SpacesController.provider);
|
final spaces = ref.watch(SpacesController.provider);
|
||||||
|
|
|
||||||
3
linux/nexus.federated.nexus.UnifiedPush.service
Normal file
3
linux/nexus.federated.nexus.UnifiedPush.service
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
[D-BUS Service]
|
||||||
|
Name=nexus.federated.nexus.UnifiedPush
|
||||||
|
Exec=/usr/bin/env FLUTTER_HEADLESS=1 nexus
|
||||||
59
linux/nix/default.nix
Normal file
59
linux/nix/default.nix
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
{ self, inputs, ... }: {
|
||||||
|
|
||||||
|
perSystem =
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
system,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
_module.args.pkgs = import inputs.nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
config = {
|
||||||
|
android_sdk.accept_license = true;
|
||||||
|
allowUnfree = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
packages =
|
||||||
|
let
|
||||||
|
default = pkgs.callPackage ./pkg {
|
||||||
|
src = self;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit default;
|
||||||
|
|
||||||
|
flatpak = inputs.nix2flatpak.lib.${system}.mkFlatpak {
|
||||||
|
appName = "Nexus";
|
||||||
|
developer = "QuadRadical";
|
||||||
|
appId = "nexus.federated.nexus";
|
||||||
|
package = default;
|
||||||
|
runtime = "org.gnome.Platform/49";
|
||||||
|
permissions = {
|
||||||
|
share = [ "network" ];
|
||||||
|
sockets = [
|
||||||
|
"pulseaudio"
|
||||||
|
"fallback-x11"
|
||||||
|
"wayland"
|
||||||
|
];
|
||||||
|
|
||||||
|
talk-names = [
|
||||||
|
"org.unifiedpush.Distributor.*"
|
||||||
|
"org.freedesktop.Notifications"
|
||||||
|
];
|
||||||
|
devices = [ "dri" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
gomuks = pkgs.callPackage ./pkg/gomuks.nix {
|
||||||
|
src = self;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
devShells.default = pkgs.callPackage ./devshell.nix { };
|
||||||
|
};
|
||||||
|
|
||||||
|
flake.nixosModules.default = import ./module.nix self;
|
||||||
|
}
|
||||||
45
linux/nix/module.nix
Normal file
45
linux/nix/module.nix
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
self:
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib)
|
||||||
|
mkIf
|
||||||
|
mkMerge
|
||||||
|
mkEnableOption
|
||||||
|
mkPackageOption
|
||||||
|
;
|
||||||
|
|
||||||
|
cfg = config.programs.nexus;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.programs.nexus = {
|
||||||
|
enable = mkEnableOption "Nexus, a simple and user-friendly Matrix client";
|
||||||
|
package = mkPackageOption self.packages.${pkgs.stdenv.hostPlatform.system} "default" { };
|
||||||
|
|
||||||
|
enableNotifications = mkEnableOption "notifications support via UnifiedPush";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable (mkMerge [
|
||||||
|
{
|
||||||
|
environment.systemPackages = [ cfg.package ];
|
||||||
|
}
|
||||||
|
(mkIf cfg.enableNotifications {
|
||||||
|
environment.systemPackages = [
|
||||||
|
pkgs.kdePackages.kunifiedpush
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.packages = [
|
||||||
|
pkgs.kdePackages.kunifiedpush
|
||||||
|
];
|
||||||
|
|
||||||
|
services.dbus.packages = [
|
||||||
|
cfg.package
|
||||||
|
];
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
@ -32,11 +32,14 @@ flutter.buildFlutterApplication {
|
||||||
emoji_text_field = "sha256-3TOys09EP2GRo6pUBGPXaqBlE39O2Cmwt42Hs1cTDKo=";
|
emoji_text_field = "sha256-3TOys09EP2GRo6pUBGPXaqBlE39O2Cmwt42Hs1cTDKo=";
|
||||||
linkify = "sha256-TpMD6+0zyY6i9l+6d8ErnVufmepCv362rCtnbOht/z4=";
|
linkify = "sha256-TpMD6+0zyY6i9l+6d8ErnVufmepCv362rCtnbOht/z4=";
|
||||||
navigation_rail_m3e = "sha256-+2awDTQnK58gGRY1nuHckG/jjxarsYSRu9ovR4i4TEc=";
|
navigation_rail_m3e = "sha256-+2awDTQnK58gGRY1nuHckG/jjxarsYSRu9ovR4i4TEc=";
|
||||||
|
unifiedpush_linux = "sha256-aIF/8oabSuuZo7K6qr4r7UBmf57qgoGAXyJ40fdntuQ=";
|
||||||
|
unifiedpush_platform_interface = "sha256-aIF/8oabSuuZo7K6qr4r7UBmf57qgoGAXyJ40fdntuQ=";
|
||||||
};
|
};
|
||||||
|
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
install -D assets/bundled/icon.svg $out/share/icons/hicolor/scalable/apps/nexus.svg
|
install -D assets/bundled/icon.svg $out/share/icons/hicolor/scalable/apps/nexus.svg
|
||||||
install -Dm755 linux/nexus.federated.nexus.desktop -t $out/share/applications
|
install -Dm755 linux/nexus.federated.nexus.desktop -t $out/share/applications
|
||||||
|
install -Dm644 linux/*.service -t $out/share/dbus-1/services
|
||||||
wrapProgram $out/bin/nexus \
|
wrapProgram $out/bin/nexus \
|
||||||
--suffix LD_LIBRARY_PATH : $out/app/nexus/lib
|
--suffix LD_LIBRARY_PATH : $out/app/nexus/lib
|
||||||
'';
|
'';
|
||||||
|
|
|
||||||
24
pubspec.lock
24
pubspec.lock
|
|
@ -1501,20 +1501,22 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.5.0"
|
version: "3.5.0"
|
||||||
unifiedpush_linux:
|
unifiedpush_linux:
|
||||||
dependency: transitive
|
dependency: "direct overridden"
|
||||||
description:
|
description:
|
||||||
name: unifiedpush_linux
|
path: unifiedpush_linux
|
||||||
sha256: c062d5eedd1cec70bcd33270cc4e01ae0ff6501f33d471167c06b34a968adfeb
|
ref: "quad/feat/should-write-service-option"
|
||||||
url: "https://pub.dev"
|
resolved-ref: "7589b07ef4280820e4adea165d3d86b219f6022c"
|
||||||
source: hosted
|
url: "https://codeberg.org/Henry-Hiles/flutter-connector"
|
||||||
version: "1.0.0"
|
source: git
|
||||||
|
version: "1.0.1"
|
||||||
unifiedpush_platform_interface:
|
unifiedpush_platform_interface:
|
||||||
dependency: transitive
|
dependency: "direct overridden"
|
||||||
description:
|
description:
|
||||||
name: unifiedpush_platform_interface
|
path: unifiedpush_platform_interface
|
||||||
sha256: "83372bc8d794b8b12ef6993b518d7be907dcfc2191bdf6de0ece5c4445d89880"
|
ref: "quad/feat/should-write-service-option"
|
||||||
url: "https://pub.dev"
|
resolved-ref: "7589b07ef4280820e4adea165d3d86b219f6022c"
|
||||||
source: hosted
|
url: "https://codeberg.org/Henry-Hiles/flutter-connector"
|
||||||
|
source: git
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
unifiedpush_storage_interface:
|
unifiedpush_storage_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
|
|
|
||||||
10
pubspec.yaml
10
pubspec.yaml
|
|
@ -20,6 +20,16 @@ environment:
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
dynamic_color: 2.1.0
|
dynamic_color: 2.1.0
|
||||||
|
unifiedpush_linux:
|
||||||
|
git:
|
||||||
|
url: https://codeberg.org/Henry-Hiles/flutter-connector
|
||||||
|
ref: quad/feat/should-write-service-option
|
||||||
|
path: unifiedpush_linux
|
||||||
|
unifiedpush_platform_interface:
|
||||||
|
git:
|
||||||
|
url: https://codeberg.org/Henry-Hiles/flutter-connector
|
||||||
|
ref: quad/feat/should-write-service-option
|
||||||
|
path: unifiedpush_platform_interface
|
||||||
path_provider_android: 2.2.23 # Pinned to avoid JNI
|
path_provider_android: 2.2.23 # Pinned to avoid JNI
|
||||||
linkify:
|
linkify:
|
||||||
git:
|
git:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue