WIP: Move to Flutter 3.47, use the improvements that come with this #63

Closed
Henry-Hiles wants to merge 4 commits from flutter-3.13 into main
157 changed files with 1166 additions and 1445 deletions

View file

@ -19,7 +19,7 @@ jobs:
- name: Set up Flutter - name: Set up Flutter
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
flutter-version: 3.44.4 flutter-version: 3.47.0
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6

View file

@ -19,7 +19,7 @@ jobs:
- name: Set up Flutter - name: Set up Flutter
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
flutter-version: 3.44.4 flutter-version: 3.47.0
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6

View file

@ -1,65 +1,65 @@
name: "Build EXE" name: "Build EXE"
on: on:
push: push:
branches: ["main"] branches: ["main"]
tags: ["*"] tags: ["*"]
workflow_dispatch: workflow_dispatch:
jobs: jobs:
build-exe: build-exe:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v6 uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
- name: Set up Flutter - name: Set up Flutter
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
flutter-version: 3.44.4 flutter-version: 3.47.0
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version-file: gomuks/go.mod go-version-file: gomuks/go.mod
- name: Setup MSYS2 - name: Setup MSYS2
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
with: with:
msystem: MINGW64 msystem: MINGW64
install: >- install: >-
mingw-w64-x86_64-gcc mingw-w64-x86_64-gcc
- name: Go build - name: Go build
run: | run: |
cd gomuks/pkg/ffi cd gomuks/pkg/ffi
go build -tags goolm,sqlite_fts5 -o ../../../libgomuks.dll -buildmode=c-shared go build -tags goolm,sqlite_fts5 -o ../../../libgomuks.dll -buildmode=c-shared
- name: Build with Flutter - name: Build with Flutter
run: | run: |
flutter pub get flutter pub get
dart scripts/generate.dart dart scripts/generate.dart
flutter pub run build_runner build flutter pub run build_runner build
flutter build windows --release flutter build windows --release
- name: Copy MinGW runtime DLLs - name: Copy MinGW runtime DLLs
shell: msys2 {0} shell: msys2 {0}
run: | run: |
cp /mingw64/bin/libgcc_s_seh-1.dll build/windows/x64/runner/Release/ cp /mingw64/bin/libgcc_s_seh-1.dll build/windows/x64/runner/Release/
cp /mingw64/bin/libwinpthread-1.dll build/windows/x64/runner/Release/ cp /mingw64/bin/libwinpthread-1.dll build/windows/x64/runner/Release/
cp /mingw64/bin/libstdc++-6.dll build/windows/x64/runner/Release/ cp /mingw64/bin/libstdc++-6.dll build/windows/x64/runner/Release/
- name: Install Inno Setup - name: Install Inno Setup
run: choco install innosetup -y run: choco install innosetup -y
- name: Build Inno Setup installer - name: Build Inno Setup installer
run: iscc windows/installer.iss run: iscc windows/installer.iss
- name: Upload installer artifact - name: Upload installer artifact
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v6
with: with:
name: windows-installer name: windows-installer
path: windows/dist/Nexus-Setup.exe path: windows/dist/Nexus-Setup.exe

View file

@ -1,12 +1,18 @@
analyzer: analyzer:
errors: errors:
invalid_annotation_target: ignore invalid_annotation_target: ignore
avoid_print: ignore avoid_print: ignore
exclude: exclude:
- "build/**" - "build/**"
- "**/*.g.dart" - "**/*.g.dart"
- "**/*.freezed.dart" - "**/*.freezed.dart"
- android/**
- ios/**
- web/**
- windows/**
- macos/**
- linux/**
include: package:flutter_lints/flutter.yaml include: package:flutter_lints/flutter.yaml
linter: linter:
rules: rules:
prefer_double_quotes: true prefer_double_quotes: true

View file

@ -1,77 +0,0 @@
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader("UTF-8") { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) {
flutterVersionCode = "1"
}
def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) {
flutterVersionName = "1.0"
}
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
namespace = "nexus.federated.nexus"
ndkVersion = flutter.ndkVersion
compileSdk = 34
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
defaultConfig {
applicationId = "nexus.federated.nexus"
minSdk = 29
targetSdkVersion flutter.targetSdkVersion
versionCode = flutterVersionCode.toInteger()
versionName = flutterVersionName
}
signingConfigs {
release {
keyAlias "key"
def storePath = keystoreProperties['path'] ?: System.getenv("KEYSTORE_PATH")
storeFile storePath ? file(storePath) : null
keyPassword keystoreProperties['password'] ?: System.getenv("KEYSTORE_PASSWORD")
storePassword keystoreProperties['password'] ?: System.getenv("KEYSTORE_PASSWORD")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
debug {
applicationIdSuffix = ".debug"
}
}
}
flutter {
source = "../.."
}

View file

@ -0,0 +1,74 @@
import java.util.Properties
plugins {
id("com.android.application")
id("dev.flutter.flutter-gradle-plugin")
}
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
keystorePropertiesFile.inputStream().use {
keystoreProperties.load(it)
}
}
android {
namespace = "nexus.federated.nexus"
compileSdk = 36
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
defaultConfig {
applicationId = "nexus.federated.nexus"
minSdk = 29
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
signingConfigs {
create("release") {
keyAlias = "key"
val storePath =
keystoreProperties["path"]?.toString()
?: System.getenv("KEYSTORE_PATH")
storeFile = storePath?.let { file(it) }
keyPassword =
keystoreProperties["password"]?.toString()
?: System.getenv("KEYSTORE_PASSWORD")
storePassword =
keystoreProperties["password"]?.toString()
?: System.getenv("KEYSTORE_PASSWORD")
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
}
debug {
applicationIdSuffix = ".debug"
}
}
}
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
flutter {
source = "../.."
}

View file

@ -1,26 +0,0 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = "../build"
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
afterEvaluate {project ->
if (project.hasProperty("android")) {
android {
compileSdkVersion 36
buildToolsVersion '33.0.1'
}
}
}
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

25
android/build.gradle.kts Normal file
View file

@ -0,0 +1,25 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
val newBuildDir: Directory =
rootProject.layout.buildDirectory
.dir("../../build")
.get()
rootProject.layout.buildDirectory.value(newBuildDir)
subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory)
}

View file

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-all.zip

View file

@ -1,25 +0,0 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.13.0" apply false
id "org.jetbrains.kotlin.android" version "2.2.20" apply false
}
include ":app"

View file

@ -0,0 +1,26 @@
pluginManagement {
val flutterSdkPath =
run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "9.3.1" apply false
id("org.jetbrains.kotlin.android") version "2.4.10" apply false
}
include(":app")

6
flake.lock generated
View file

@ -88,11 +88,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1785967620, "lastModified": 1786862985,
"narHash": "sha256-IItrdb7Puk05RqOBWZYFC5X6Wl1sJmCfh5MWVHw5iMM=", "narHash": "sha256-FBJRXmbGXiSUDvYEbfLYRkckayyZ6SK1UEqhCrIZ2Cs=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "b7c2ada94fe99c15b0dbcf4d11fd7850b957a436", "rev": "e5bdc4a41d4c072fe1e3787eaa0320a384741d44",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -6,10 +6,8 @@ import "package:nexus/models/content/content.dart";
import "package:nexus/models/content/message.dart"; import "package:nexus/models/content/message.dart";
import "package:path/path.dart"; import "package:path/path.dart";
class AttachmentController extends Notifier<(String, MessageContent?)?> { class AttachmentController(final String roomId)
final String roomId; extends Notifier<(String, MessageContent?)?> {
AttachmentController(this.roomId);
@override @override
Null build() => null; Null build() => null;

View file

@ -4,10 +4,8 @@ import "package:nexus/controllers/client_id.dart";
import "package:nexus/models/oauth_auth_code_response.dart"; import "package:nexus/models/oauth_auth_code_response.dart";
import "package:nexus/models/requests/oauth/get_auth_url.dart"; import "package:nexus/models/requests/oauth/get_auth_url.dart";
class AuthUrlController extends AsyncNotifier<OAuthAuthCodeResponse> { class AuthUrlController(final Uri homeserver)
final Uri homeserver; extends AsyncNotifier<OAuthAuthCodeResponse> {
AuthUrlController(this.homeserver);
@override @override
Future<OAuthAuthCodeResponse> build() async => ref Future<OAuthAuthCodeResponse> build() async => ref
.watch(ClientController.provider.notifier) .watch(ClientController.provider.notifier)

View file

@ -1,19 +1,17 @@
import "dart:async"; import "dart:async";
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/user.dart"; import "package:nexus/controllers/user.dart";
import "package:nexus/models/content/membership.dart"; import "package:nexus/models/content/membership.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
class AuthorController extends AsyncNotifier<MembershipContent> { class AuthorController(final Event event)
final Event event; extends AsyncNotifier<MembershipContent> {
AuthorController(this.event);
@override @override
Future<MembershipContent> build() async { Future<MembershipContent> build() async {
final member = await ref.watch( final member = await ref.watch(
UserController.provider( UserController.provider(.new(roomId: event.roomId, userId: event.sender))
.new(roomId: event.roomId, userId: event.sender), .future,
).future,
); );
return .new( return .new(

View file

@ -1,10 +1,7 @@
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client.dart";
class ClientIdController extends AsyncNotifier<String> { class ClientIdController(final Uri homeserver) extends AsyncNotifier<String> {
final Uri homeserver;
ClientIdController(this.homeserver);
@override @override
Future<String> build() => ref Future<String> build() => ref
.watch(ClientController.provider.notifier) .watch(ClientController.provider.notifier)

View file

@ -1,7 +1,7 @@
import "dart:convert"; import "dart:convert";
import "package:emoji_text_field/models/emoji_category.dart"; import "package:emoji_text_field/models/emoji_category.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart"; import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:http/http.dart"; import "package:http/http.dart";
import "package:nexus/models/emoji.dart"; import "package:nexus/models/emoji.dart";

View file

@ -5,10 +5,8 @@ import "package:nexus/controllers/rooms.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
import "package:nexus/models/requests/get_event.dart"; import "package:nexus/models/requests/get_event.dart";
class EventController extends AsyncNotifier<Event?> { class EventController(final GetEventRequest request)
final GetEventRequest request; extends AsyncNotifier<Event?> {
EventController(this.request);
@override @override
Future<Event?> build() async { Future<Event?> build() async {
final room = ref.watch( final room = ref.watch(

View file

@ -1,10 +1,7 @@
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 extends Notifier<String?> { class KeyController(final String key) extends Notifier<String?> {
final String key;
KeyController(this.key);
static const String spaceKey = "space"; static const String spaceKey = "space";
static const String roomKey = "room"; static const String roomKey = "room";

View file

@ -6,10 +6,8 @@ import "package:nexus/models/content/content.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
import "package:nexus/models/requests/get_room_state.dart"; import "package:nexus/models/requests/get_room_state.dart";
class MembersController extends AsyncNotifier<ISet<Event>> { class MembersController(final String roomId)
final String roomId; extends AsyncNotifier<ISet<Event>> {
MembersController(this.roomId);
@override @override
Future<ISet<Event>> build() async { Future<ISet<Event>> build() async {
final room = ref.watch( final room = ref.watch(

View file

@ -5,10 +5,8 @@ import "package:nexus/models/configs/members_by_status.dart";
import "package:nexus/models/content/membership.dart"; import "package:nexus/models/content/membership.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
class MembersByStatusController extends AsyncNotifier<ISet<Event>> { class MembersByStatusController(final MembersByStatusConfig config)
final MembersByStatusConfig config; extends AsyncNotifier<ISet<Event>> {
MembersByStatusController(this.config);
@override @override
Future<ISet<Event>> build() => ref.watch( Future<ISet<Event>> build() => ref.watch(
MembersController.provider(config.roomId).selectAsync( MembersController.provider(config.roomId).selectAsync(

View file

@ -8,11 +8,8 @@ import "package:nexus/models/content/content.dart";
import "package:nexus/models/content/power_levels.dart"; import "package:nexus/models/content/power_levels.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
class MembersGroupedController class MembersGroupedController(final MembersByStatusConfig config)
extends AsyncNotifier<IList<MapEntry<int?, ISet<Event>>>> { extends AsyncNotifier<IList<MapEntry<int?, ISet<Event>>>> {
final MembersByStatusConfig config;
MembersGroupedController(this.config);
@override @override
Future<IList<MapEntry<int?, ISet<Event>>>> build() async { Future<IList<MapEntry<int?, ISet<Event>>>> build() async {
final room = ref.watch( final room = ref.watch(

View file

@ -1,11 +1,10 @@
import "dart:async"; import "dart:async";
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
class MultiProviderController extends AsyncNotifier<void> { class MultiProviderController(final IList<AsyncNotifierProvider> providers)
MultiProviderController(this.providers); extends AsyncNotifier<void> {
final IList<AsyncNotifierProvider> providers;
@override @override
Future<void> build() => Future<void> build() =>
.wait(providers.map((provider) => ref.watch(provider.future))); .wait(providers.map((provider) => ref.watch(provider.future)));

View file

@ -4,10 +4,8 @@ import "package:nexus/controllers/event.dart";
import "package:nexus/controllers/pinned_ids.dart"; import "package:nexus/controllers/pinned_ids.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
class PinnedEventsController extends AsyncNotifier<IList<Event>> { class PinnedEventsController(final String roomId)
final String roomId; extends AsyncNotifier<IList<Event>> {
PinnedEventsController(this.roomId);
@override @override
Future<IList<Event>> build() async { Future<IList<Event>> build() async {
final pinIds = ref.watch(PinnedIdsController.provider(roomId)); final pinIds = ref.watch(PinnedIdsController.provider(roomId));
@ -15,9 +13,8 @@ class PinnedEventsController extends AsyncNotifier<IList<Event>> {
return (await Future.wait( return (await Future.wait(
pinIds.map( pinIds.map(
(eventId) => ref.watch( (eventId) => ref.watch(
EventController.provider( EventController.provider(.new(eventId: eventId, roomId: roomId))
.new(eventId: eventId, roomId: roomId), .future,
).future,
), ),
), ),
)).nonNulls.toIList(); )).nonNulls.toIList();

View file

@ -5,10 +5,7 @@ import "package:nexus/controllers/rooms.dart";
import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/content.dart";
import "package:nexus/models/content/pinned_events.dart"; import "package:nexus/models/content/pinned_events.dart";
class PinnedIdsController extends Notifier<IList<String>> { class PinnedIdsController(final String roomId) extends Notifier<IList<String>> {
final String roomId;
PinnedIdsController(this.roomId);
@override @override
IList<String> build() { IList<String> build() {
final room = ref.watch( final room = ref.watch(

View file

@ -6,10 +6,8 @@ import "package:nexus/models/configs/power_level.dart";
import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/content.dart";
import "package:nexus/models/content/power_levels.dart"; import "package:nexus/models/content/power_levels.dart";
class PowerLevelController extends Notifier<bool> { class PowerLevelController(final PowerLevelConfig config)
final PowerLevelConfig config; extends Notifier<bool> {
PowerLevelController(this.config);
@override @override
bool build() { bool build() {
if (config case EventPowerLevelConfig(:final eventType)) { if (config case EventPowerLevelConfig(:final eventType)) {

View file

@ -2,10 +2,8 @@ import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client.dart";
import "package:nexus/models/profile_response.dart"; import "package:nexus/models/profile_response.dart";
class ProfileController extends AsyncNotifier<ProfileResponse> { class ProfileController(final String userId)
final String userId; extends AsyncNotifier<ProfileResponse> {
ProfileController(this.userId);
@override @override
Future<ProfileResponse> build() { Future<ProfileResponse> build() {
final client = ref.watch(ClientController.provider.notifier); final client = ref.watch(ClientController.provider.notifier);

View file

@ -5,10 +5,8 @@ import "package:nexus/controllers/rooms.dart";
import "package:nexus/models/configs/reactions.dart"; import "package:nexus/models/configs/reactions.dart";
import "package:nexus/models/content/reaction.dart"; import "package:nexus/models/content/reaction.dart";
class ReactionsController extends AsyncNotifier<IMap<String, IList<String>>> { class ReactionsController(final ReactionsConfig config)
final ReactionsConfig config; extends AsyncNotifier<IMap<String, IList<String>>> {
ReactionsController(this.config);
@override @override
Future<IMap<String, IList<String>>> build() async { Future<IMap<String, IList<String>>> build() async {
final eventInfo = ref.watch( final eventInfo = ref.watch(

View file

@ -1,5 +1,6 @@
import "dart:async"; import "dart:async";
import "dart:math"; import "dart:math";
import "package:collection/collection.dart"; import "package:collection/collection.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
@ -15,10 +16,8 @@ import "package:nexus/models/relation_type.dart";
import "package:nexus/models/requests/send_message.dart"; import "package:nexus/models/requests/send_message.dart";
import "package:nexus/models/room.dart"; import "package:nexus/models/room.dart";
class RoomChatController extends AsyncNotifier<IList<Event>?> { class RoomChatController(final String roomId)
final String roomId; extends AsyncNotifier<IList<Event>?> {
RoomChatController(this.roomId);
@override @override
Future<IList<Event>?> build() async { Future<IList<Event>?> build() async {
final client = ref.watch(ClientController.provider.notifier); final client = ref.watch(ClientController.provider.notifier);

View file

@ -4,10 +4,7 @@ import "package:nexus/models/content/content.dart";
import "package:nexus/models/content/create.dart"; import "package:nexus/models/content/create.dart";
import "package:nexus/models/room.dart"; import "package:nexus/models/room.dart";
class RoomCreatorsController extends Notifier<IList<String>> { class RoomCreatorsController(final Room room) extends Notifier<IList<String>> {
final Room room;
RoomCreatorsController(this.room);
@override @override
IList<String> build() { IList<String> build() {
final createRowId = room.state[EventType.create.type]?[""]; final createRowId = room.state[EventType.create.type]?[""];

View file

@ -3,10 +3,8 @@ import "package:nexus/controllers/client.dart";
import "package:nexus/models/requests/join_room.dart"; import "package:nexus/models/requests/join_room.dart";
import "package:nexus/models/room_summary.dart"; import "package:nexus/models/room_summary.dart";
class RoomSummaryController extends AsyncNotifier<RoomSummary> { class RoomSummaryController(final JoinRoomRequest request)
final JoinRoomRequest request; extends AsyncNotifier<RoomSummary> {
RoomSummaryController(this.request);
@override @override
Future<RoomSummary> build() => Future<RoomSummary> build() =>
ref.watch(ClientController.provider.notifier).getRoomSummary(request); ref.watch(ClientController.provider.notifier).getRoomSummary(request);

View file

@ -1,6 +1,6 @@
import "dart:io"; import "dart:io";
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart"; import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:intl/intl.dart"; import "package:intl/intl.dart";
import "package:m3e_buttons/m3e_buttons.dart"; import "package:m3e_buttons/m3e_buttons.dart";

View file

@ -1,6 +1,6 @@
import "package:collection/collection.dart"; import "package:collection/collection.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart"; import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/account_data.dart"; import "package:nexus/controllers/account_data.dart";
import "package:nexus/controllers/rooms.dart"; import "package:nexus/controllers/rooms.dart";

View file

@ -3,10 +3,8 @@ import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client.dart";
import "package:nexus/models/open_graph_data.dart"; import "package:nexus/models/open_graph_data.dart";
class UrlPreviewController extends AsyncNotifier<OpenGraphData?> { class UrlPreviewController(final Uri url)
final Uri url; extends AsyncNotifier<OpenGraphData?> {
UrlPreviewController(this.url);
@override @override
Future<OpenGraphData?> build() async { Future<OpenGraphData?> build() async {
if (url.host == "matrix.to") return null; if (url.host == "matrix.to") return null;

View file

@ -7,10 +7,7 @@ import "package:nexus/models/content/membership.dart";
import "package:nexus/models/content/power_levels.dart"; import "package:nexus/models/content/power_levels.dart";
import "package:nexus/models/room.dart"; import "package:nexus/models/room.dart";
class ViaController extends Notifier<String> { class ViaController(final Room room) extends Notifier<String> {
final Room room;
ViaController(this.room);
@override @override
String build() { String build() {
final servers = <String>{}; final servers = <String>{};

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart"; import "package:material_ui/material_ui.dart";
extension SchemeToTheme on ColorScheme { extension SchemeToTheme on ColorScheme {
ThemeData get theme { ThemeData get theme {

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart"; import "package:material_ui/material_ui.dart";
import "package:flutter_svg/flutter_svg.dart"; import "package:flutter_svg/flutter_svg.dart";
import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:m3e_card_list/m3e_card_list.dart"; import "package:m3e_card_list/m3e_card_list.dart";

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart"; import "package:material_ui/material_ui.dart";
extension ShowContextMenu on BuildContext { extension ShowContextMenu on BuildContext {
void showContextMenu({ void showContextMenu({

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart"; import "package:material_ui/material_ui.dart";
import "package:nexus/models/content/membership.dart"; import "package:nexus/models/content/membership.dart";
import "package:nexus/widgets/user_bottom_sheet.dart"; import "package:nexus/widgets/user_bottom_sheet.dart";

View file

@ -1,5 +1,5 @@
import "package:color_hash/color_hash.dart"; import "package:color_hash/color_hash.dart";
import "package:flutter/material.dart"; import "package:material_ui/material_ui.dart";
extension ToColor on String { extension ToColor on String {
Color get colorHash => ColorHash(this, lightness: .5, saturation: .7).color; Color get colorHash => ColorHash(this, lightness: .5, saturation: .7).color;

View file

@ -2,10 +2,7 @@ import "package:flutter/services.dart";
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:url_launcher/url_launcher.dart" as ul; import "package:url_launcher/url_launcher.dart" as ul;
class LaunchHelper { class LaunchHelper(Ref ref) {
final Ref ref;
LaunchHelper(this.ref);
Future<bool> launchUrl(Uri url, {bool useWebview = false}) async { Future<bool> launchUrl(Uri url, {bool useWebview = false}) async {
try { try {
return await ul.launchUrl( return await ul.launchUrl(

View file

@ -1,14 +1,12 @@
import "dart:ui"; import "dart:ui";
import "package:flutter/widgets.dart"; import "package:flutter/widgets.dart";
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client.dart";
import "package:nexus/models/requests/download_media.dart"; import "package:nexus/models/requests/download_media.dart";
class MxcImage extends ImageProvider<MxcImage> { class MxcImage(final WidgetRef ref, final DownloadMediaRequest request)
final WidgetRef ref; extends ImageProvider<MxcImage> {
final DownloadMediaRequest request;
const MxcImage(this.ref, this.request);
@override @override
Future<MxcImage> obtainKey(ImageConfiguration configuration) => Future<MxcImage> obtainKey(ImageConfiguration configuration) =>
Future.value(this); Future.value(this);

View file

@ -1,4 +1,5 @@
import "dart:io"; import "dart:io";
import "package:dynamic_color/dynamic_color.dart"; import "package:dynamic_color/dynamic_color.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/foundation.dart"; import "package:flutter/foundation.dart";
@ -18,7 +19,7 @@ import "package:nexus/pages/verify.dart";
import "package:nexus/widgets/error_dialog.dart"; import "package:nexus/widgets/error_dialog.dart";
import "package:nexus/widgets/loading.dart"; import "package:nexus/widgets/loading.dart";
import "package:window_manager/window_manager.dart"; import "package:window_manager/window_manager.dart";
import "package:flutter/material.dart"; import "package:material_ui/material_ui.dart";
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@ -94,9 +95,7 @@ void main() async {
); );
} }
class App extends StatelessWidget { class const App({super.key}) extends StatelessWidget {
const App({super.key});
@override @override
Widget build(BuildContext context) => DynamicColorBuilder( Widget build(BuildContext context) => DynamicColorBuilder(
builder: (lightDynamic, darkDynamic) => Consumer( builder: (lightDynamic, darkDynamic) => Consumer(

View file

@ -1,11 +1,25 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "account_data.freezed.dart"; part "account_data.freezed.dart";
part "account_data.g.dart"; part "account_data.g.dart";
@freezed @freezed
abstract class AccountData with _$AccountData { sealed class const AccountData({
const AccountData._(); @JsonKey(name: AccountData.invitePermissionConfigKey)
InvitePermissionConfig invitePermissionConfig =
const _InvitePermissionConfig(),
@JsonKey(name: AccountData.directKey)
IMap<String, IList<String>> directMessages = const IMap.empty(),
@JsonKey(
name: AccountData.recentEmojiKey,
readValue: AccountData.readRecentEmojiValue,
toJson: AccountData.recentEmojiToJson,
)
IList<RecentEmoji> recentEmoji = const IList.empty(),
}) with _$AccountData {
static List<dynamic>? readRecentEmojiValue( static List<dynamic>? readRecentEmojiValue(
Map<dynamic, dynamic> json, Map<dynamic, dynamic> json,
String key, String key,
@ -19,45 +33,22 @@ abstract class AccountData with _$AccountData {
static const directKey = "m.direct"; static const directKey = "m.direct";
static const recentEmojiKey = "m.recent_emoji"; static const recentEmojiKey = "m.recent_emoji";
const factory AccountData({
@JsonKey(name: AccountData.invitePermissionConfigKey)
@Default(InvitePermissionConfig())
InvitePermissionConfig invitePermissionConfig,
@JsonKey(name: AccountData.directKey)
@Default(IMap.empty())
IMap<String, IList<String>> directMessages,
@JsonKey(
name: AccountData.recentEmojiKey,
readValue: AccountData.readRecentEmojiValue,
toJson: AccountData.recentEmojiToJson,
)
@Default(IList.empty())
IList<RecentEmoji> recentEmoji,
}) = _AccountData;
factory AccountData.fromJson(Map<String, Object?> json) => factory AccountData.fromJson(Map<String, Object?> json) =>
_$AccountDataFromJson(json); _$AccountDataFromJson(json);
} }
@freezed @freezed
abstract class InvitePermissionConfig with _$InvitePermissionConfig { sealed class const InvitePermissionConfig({
const factory InvitePermissionConfig({ @JsonKey(unknownEnumValue: DefaultInviteAction.allow)
@JsonKey(unknownEnumValue: DefaultInviteAction.allow) DefaultInviteAction defaultAction = DefaultInviteAction.allow,
@Default(DefaultInviteAction.allow) }) with _$InvitePermissionConfig {
DefaultInviteAction defaultAction,
}) = _InvitePermissionConfig;
factory InvitePermissionConfig.fromJson(Map<String, Object?> json) => factory InvitePermissionConfig.fromJson(Map<String, Object?> json) =>
_$InvitePermissionConfigFromJson(json); _$InvitePermissionConfigFromJson(json);
} }
@freezed @freezed
abstract class RecentEmoji with _$RecentEmoji { sealed class const RecentEmoji({required String emoji, required int total})
const factory RecentEmoji({required String emoji, required int total}) = with _$RecentEmoji {
_RecentEmoji;
factory RecentEmoji.fromJson(Map<String, Object?> json) => factory RecentEmoji.fromJson(Map<String, Object?> json) =>
_$RecentEmojiFromJson(json); _$RecentEmojiFromJson(json);
} }

View file

@ -1,17 +1,16 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "client_state.freezed.dart"; part "client_state.freezed.dart";
part "client_state.g.dart"; part "client_state.g.dart";
@freezed @freezed
abstract class ClientState with _$ClientState { sealed class const ClientState({
const factory ClientState({ required bool isInitialized,
required bool isInitialized, required bool isLoggedIn,
required bool isLoggedIn, required bool isVerified,
required bool isVerified, required String? userId,
required String? userId, required String? homeserverUrl,
required String? homeserverUrl, }) with _$ClientState {
}) = _ClientState;
factory ClientState.fromJson(Map<String, Object?> json) => factory ClientState.fromJson(Map<String, Object?> json) =>
_$ClientStateFromJson(json); _$ClientStateFromJson(json);
} }

View file

@ -1,15 +1,14 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/membership_status.dart"; import "package:nexus/models/membership_status.dart";
part "members_by_status.freezed.dart"; part "members_by_status.freezed.dart";
part "members_by_status.g.dart"; part "members_by_status.g.dart";
@freezed @freezed
abstract class MembersByStatusConfig with _$MembersByStatusConfig { sealed class const MembersByStatusConfig({
const factory MembersByStatusConfig({ required String roomId,
required String roomId, required MembershipStatus status,
required MembershipStatus status, }) with _$MembersByStatusConfig {
}) = _MembersByStatusConfig;
factory MembersByStatusConfig.fromJson(Map<String, Object?> json) => factory MembersByStatusConfig.fromJson(Map<String, Object?> json) =>
_$MembersByStatusConfigFromJson(json); _$MembersByStatusConfigFromJson(json);
} }

View file

@ -1,6 +1,7 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/content.dart";
import "package:nexus/models/membership_action.dart"; import "package:nexus/models/membership_action.dart";
part "power_level.freezed.dart"; part "power_level.freezed.dart";
@freezed @freezed

View file

@ -1,14 +1,13 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "reactions.freezed.dart"; part "reactions.freezed.dart";
part "reactions.g.dart"; part "reactions.g.dart";
@freezed @freezed
abstract class ReactionsConfig with _$ReactionsConfig { sealed class const ReactionsConfig({
const factory ReactionsConfig({ required String roomId,
required String roomId, required int eventRowId,
required int eventRowId, }) with _$ReactionsConfig {
}) = _ReactionsConfig;
factory ReactionsConfig.fromJson(Map<String, Object?> json) => factory ReactionsConfig.fromJson(Map<String, Object?> json) =>
_$ReactionsConfigFromJson(json); _$ReactionsConfigFromJson(json);
} }

View file

@ -1,12 +1,11 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "user.freezed.dart"; part "user.freezed.dart";
part "user.g.dart"; part "user.g.dart";
@freezed @freezed
abstract class UserConfig with _$UserConfig { sealed class const UserConfig({String? roomId, required String userId})
const factory UserConfig({required String? roomId, required String userId}) = with _$UserConfig {
_UserConfig;
factory UserConfig.fromJson(Map<String, Object?> json) => factory UserConfig.fromJson(Map<String, Object?> json) =>
_$UserConfigFromJson(json); _$UserConfigFromJson(json);
} }

View file

@ -5,7 +5,7 @@ part "avatar.freezed.dart";
part "avatar.g.dart"; part "avatar.g.dart";
@freezed @freezed
abstract class AvatarContent extends Content with _$AvatarContent { sealed class AvatarContent extends Content with _$AvatarContent {
AvatarContent._(); AvatarContent._();
factory AvatarContent({ImageInfo? info, Uri? url}) = _AvatarContent; factory AvatarContent({ImageInfo? info, Uri? url}) = _AvatarContent;

View file

@ -5,7 +5,7 @@ part "canonical_alias.freezed.dart";
part "canonical_alias.g.dart"; part "canonical_alias.g.dart";
@freezed @freezed
abstract class CanonicalAliasContent extends Content sealed class CanonicalAliasContent extends Content
with _$CanonicalAliasContent { with _$CanonicalAliasContent {
CanonicalAliasContent._(); CanonicalAliasContent._();
factory CanonicalAliasContent({ factory CanonicalAliasContent({

View file

@ -19,9 +19,11 @@ import "package:nexus/models/content/history_visibility.dart";
class Content { class Content {
final Error? parseError; final Error? parseError;
Content({this.parseError});
factory Content.fromJson(Map<String, dynamic> json) => Content(); const Content({this.parseError});
factory Content.fromJson(Map<String, dynamic> json) => const Content();
Map<String, dynamic> toJson() => {}; Map<String, dynamic> toJson() => {};
static Map<String, dynamic> readValue(Map<dynamic, dynamic> json, _) => static Map<String, dynamic> readValue(Map<dynamic, dynamic> json, _) =>
@ -34,13 +36,16 @@ class Content {
?.contentFromJson ?? ?.contentFromJson ??
Content.fromJson)(json); Content.fromJson)(json);
} catch (error) { } catch (error) {
if (error is Error) return .new(parseError: error); if (error is Error) return Content(parseError: error);
rethrow; rethrow;
} }
} }
} }
enum EventType { enum EventType(
final String type,
final Content Function(Map<String, dynamic> json) contentFromJson,
) {
encrypted("m.room.encrypted", EncryptedContent.fromJson), encrypted("m.room.encrypted", EncryptedContent.fromJson),
redaction("m.room.redaction", RedactionContent.fromJson), redaction("m.room.redaction", RedactionContent.fromJson),
encryption("m.room.encryption", EncryptionContent.fromJson), encryption("m.room.encryption", EncryptionContent.fromJson),
@ -61,8 +66,4 @@ enum EventType {
reaction("m.reaction", ReactionContent.fromJson), reaction("m.reaction", ReactionContent.fromJson),
pinnedEvents("m.room.pinned_events", PinnedEventsContent.fromJson), pinnedEvents("m.room.pinned_events", PinnedEventsContent.fromJson),
message("m.room.message", MessageContent.fromJson); message("m.room.message", MessageContent.fromJson);
final String type;
final Content Function(Map<String, dynamic> json) contentFromJson;
const EventType(this.type, this.contentFromJson);
} }

View file

@ -5,7 +5,7 @@ part "create.freezed.dart";
part "create.g.dart"; part "create.g.dart";
@freezed @freezed
abstract class CreateContent extends Content with _$CreateContent { sealed class CreateContent extends Content with _$CreateContent {
CreateContent._(); CreateContent._();
factory CreateContent({ factory CreateContent({
@JsonKey(name: "additional_creators") @JsonKey(name: "additional_creators")
@ -31,9 +31,7 @@ enum RoomType {
} }
@freezed @freezed
abstract class PreviousRoom with _$PreviousRoom { sealed class const PreviousRoom({required String roomId}) with _$PreviousRoom {
const factory PreviousRoom({required String roomId}) = _PreviousRoom;
factory PreviousRoom.fromJson(Map<String, Object?> json) => factory PreviousRoom.fromJson(Map<String, Object?> json) =>
_$PreviousRoomFromJson(json); _$PreviousRoomFromJson(json);
} }

View file

@ -4,7 +4,7 @@ part "encrypted.freezed.dart";
part "encrypted.g.dart"; part "encrypted.g.dart";
@freezed @freezed
abstract class EncryptedContent extends Content with _$EncryptedContent { sealed class EncryptedContent extends Content with _$EncryptedContent {
EncryptedContent._(); EncryptedContent._();
factory EncryptedContent() = _EncryptedContent; factory EncryptedContent() = _EncryptedContent;

View file

@ -4,7 +4,7 @@ part "encryption.freezed.dart";
part "encryption.g.dart"; part "encryption.g.dart";
@freezed @freezed
abstract class EncryptionContent extends Content with _$EncryptionContent { sealed class EncryptionContent extends Content with _$EncryptionContent {
EncryptionContent._(); EncryptionContent._();
factory EncryptionContent({ factory EncryptionContent({
required String algorithm, required String algorithm,

View file

@ -4,7 +4,7 @@ part "history_visibility.freezed.dart";
part "history_visibility.g.dart"; part "history_visibility.g.dart";
@freezed @freezed
abstract class HistoryVisibilityContent extends Content sealed class HistoryVisibilityContent extends Content
with _$HistoryVisibilityContent { with _$HistoryVisibilityContent {
HistoryVisibilityContent._(); HistoryVisibilityContent._();
factory HistoryVisibilityContent({ factory HistoryVisibilityContent({

View file

@ -6,7 +6,7 @@ part "join_rules.freezed.dart";
part "join_rules.g.dart"; part "join_rules.g.dart";
@freezed @freezed
abstract class JoinRulesContent extends Content with _$JoinRulesContent { sealed class JoinRulesContent extends Content with _$JoinRulesContent {
JoinRulesContent._(); JoinRulesContent._();
factory JoinRulesContent({ factory JoinRulesContent({
required JoinRule joinRule, required JoinRule joinRule,
@ -18,12 +18,10 @@ abstract class JoinRulesContent extends Content with _$JoinRulesContent {
} }
@freezed @freezed
abstract class AllowCondition with _$AllowCondition { sealed class const AllowCondition({
const factory AllowCondition({ String? roomId,
String? roomId, required AllowConditionType type,
required AllowConditionType type, }) with _$AllowCondition {
}) = _AllowCondition;
factory AllowCondition.fromJson(Map<String, Object?> json) => factory AllowCondition.fromJson(Map<String, Object?> json) =>
_$AllowConditionFromJson(json); _$AllowConditionFromJson(json);
} }

View file

@ -5,7 +5,7 @@ part "membership.freezed.dart";
part "membership.g.dart"; part "membership.g.dart";
@freezed @freezed
abstract class MembershipContent extends Content with _$MembershipContent { sealed class MembershipContent extends Content with _$MembershipContent {
MembershipContent._(); MembershipContent._();
static String? displaynameFromJson(String? displayName) => static String? displaynameFromJson(String? displayName) =>

View file

@ -10,7 +10,7 @@ part "message.g.dart";
typedef EncryptedFile = Map<String, dynamic>; typedef EncryptedFile = Map<String, dynamic>;
@Freezed(unionKey: "msgtype", fallbackUnion: "default") @Freezed(unionKey: "msgtype", fallbackUnion: "default")
abstract class MessageContent extends Content with _$MessageContent { sealed class MessageContent extends Content with _$MessageContent {
MessageContent._(); MessageContent._();
static String? mediaUrlFromJson(Map<dynamic, dynamic> json, String key) => static String? mediaUrlFromJson(Map<dynamic, dynamic> json, String key) =>
json[key] ?? json["file"]?[key]; json[key] ?? json["file"]?[key];

View file

@ -4,7 +4,7 @@ part "name.freezed.dart";
part "name.g.dart"; part "name.g.dart";
@freezed @freezed
abstract class NameContent extends Content with _$NameContent { sealed class NameContent extends Content with _$NameContent {
NameContent._(); NameContent._();
factory NameContent({required String name}) = _NameContent; factory NameContent({required String name}) = _NameContent;

View file

@ -5,7 +5,7 @@ part "pinned_events.freezed.dart";
part "pinned_events.g.dart"; part "pinned_events.g.dart";
@freezed @freezed
abstract class PinnedEventsContent extends Content with _$PinnedEventsContent { sealed class PinnedEventsContent extends Content with _$PinnedEventsContent {
PinnedEventsContent._(); PinnedEventsContent._();
factory PinnedEventsContent({ factory PinnedEventsContent({
@Default(IList.empty()) @JsonKey(name: "pinned") IList<String> pinnedEvents, @Default(IList.empty()) @JsonKey(name: "pinned") IList<String> pinnedEvents,

View file

@ -5,7 +5,7 @@ part "power_levels.freezed.dart";
part "power_levels.g.dart"; part "power_levels.g.dart";
@freezed @freezed
abstract class PowerLevelsContent extends Content with _$PowerLevelsContent { sealed class PowerLevelsContent extends Content with _$PowerLevelsContent {
PowerLevelsContent._(); PowerLevelsContent._();
factory PowerLevelsContent({ factory PowerLevelsContent({
@Default(IMap.empty()) IMap<String, int> events, @Default(IMap.empty()) IMap<String, int> events,
@ -25,12 +25,10 @@ abstract class PowerLevelsContent extends Content with _$PowerLevelsContent {
} }
@freezed @freezed
abstract class Notifications with _$Notifications { sealed class const Notifications({
const factory Notifications({ int room = 50,
@Default(50) int room, IMap<String, int> other = const IMap.empty(),
@Default(IMapConst({})) IMap<String, int> other, }) with _$Notifications {
}) = _Notifications;
factory Notifications.fromJson(Map<String, Object?> json) => factory Notifications.fromJson(Map<String, Object?> json) =>
_$NotificationsFromJson(json); _$NotificationsFromJson(json);
} }

View file

@ -4,7 +4,7 @@ part "reaction.freezed.dart";
part "reaction.g.dart"; part "reaction.g.dart";
@Freezed(toJson: false) @Freezed(toJson: false)
abstract class ReactionContent extends Content with _$ReactionContent { sealed class ReactionContent extends Content with _$ReactionContent {
ReactionContent._(); ReactionContent._();
static String? keyJsonFromJson(Map<dynamic, dynamic> json, String key) => static String? keyJsonFromJson(Map<dynamic, dynamic> json, String key) =>
json["m.relates_to"]?["key"]; json["m.relates_to"]?["key"];

View file

@ -4,7 +4,7 @@ part "redaction.freezed.dart";
part "redaction.g.dart"; part "redaction.g.dart";
@freezed @freezed
abstract class RedactionContent extends Content with _$RedactionContent { sealed class RedactionContent extends Content with _$RedactionContent {
RedactionContent._(); RedactionContent._();
factory RedactionContent({String? reason, String? redacts}) = factory RedactionContent({String? reason, String? redacts}) =
_RedactionContent; _RedactionContent;

View file

@ -5,7 +5,7 @@ part "server_acl.freezed.dart";
part "server_acl.g.dart"; part "server_acl.g.dart";
@freezed @freezed
abstract class ServerACLContent extends Content with _$ServerACLContent { sealed class ServerACLContent extends Content with _$ServerACLContent {
ServerACLContent._(); ServerACLContent._();
factory ServerACLContent({ factory ServerACLContent({
@Default(IList.empty()) IList<String> allow, @Default(IList.empty()) IList<String> allow,

View file

@ -5,7 +5,7 @@ part "sticker.freezed.dart";
part "sticker.g.dart"; part "sticker.g.dart";
@freezed @freezed
abstract class StickerContent extends Content with _$StickerContent { sealed class StickerContent extends Content with _$StickerContent {
StickerContent._(); StickerContent._();
factory StickerContent({ factory StickerContent({
required String body, required String body,

View file

@ -1,11 +1,12 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/content.dart";
part "topic.freezed.dart"; part "topic.freezed.dart";
part "topic.g.dart"; part "topic.g.dart";
@freezed @freezed
abstract class TopicContent extends Content with _$TopicContent { sealed class TopicContent extends Content with _$TopicContent {
TopicContent._(); TopicContent._();
factory TopicContent({ factory TopicContent({
required String topic, required String topic,
@ -17,24 +18,18 @@ abstract class TopicContent extends Content with _$TopicContent {
} }
@freezed @freezed
abstract class TopicContentBlock with _$TopicContentBlock { sealed class const TopicContentBlock({
factory TopicContentBlock({ IList<TextualRepresentation> representations = const IList.empty(),
@Default(IList.empty()) }) with _$TopicContentBlock {
@JsonKey(name: "m.text")
IList<TextualRepresentation> representations,
}) = _TopicContentBlock;
factory TopicContentBlock.fromJson(Map<String, Object?> json) => factory TopicContentBlock.fromJson(Map<String, Object?> json) =>
_$TopicContentBlockFromJson(json); _$TopicContentBlockFromJson(json);
} }
@freezed @freezed
abstract class TextualRepresentation with _$TextualRepresentation { sealed class const TextualRepresentation({
factory TextualRepresentation({ required String body,
required String body, String mimetype = "text/plain",
@Default("text/plain") String mimetype, }) with _$TextualRepresentation {
}) = _TextualRepresentation;
factory TextualRepresentation.fromJson(Map<String, Object?> json) => factory TextualRepresentation.fromJson(Map<String, Object?> json) =>
_$TextualRepresentationFromJson(json); _$TextualRepresentationFromJson(json);
} }

View file

@ -1,17 +0,0 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart";
part "emoji.freezed.dart";
part "emoji.g.dart";
@freezed
abstract class Emoji with _$Emoji {
const factory Emoji({
required String emoji,
required String category,
required IList<String> aliases,
required String description,
required IList<String> tags,
}) = _Emoji;
factory Emoji.fromJson(Map<String, Object?> json) => _$EmojiFromJson(json);
}

View file

@ -3,11 +3,36 @@ import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/content.dart";
import "package:nexus/models/epoch_date_time_converter.dart"; import "package:nexus/models/epoch_date_time_converter.dart";
import "package:nexus/models/profile_response.dart"; import "package:nexus/models/profile_response.dart";
part "event.freezed.dart"; part "event.freezed.dart";
part "event.g.dart"; part "event.g.dart";
@freezed @freezed
abstract class Event with _$Event { sealed class const Event({
@JsonKey(name: "rowid") required int rowId,
@JsonKey(name: "timeline_rowid") required int timelineRowId,
required String roomId,
required String eventId,
required String sender,
@JsonKey(readValue: Event.typeJsonFromJson) required String type,
String? stateKey,
@EpochDateTimeConverter() required DateTime timestamp,
IMap<String, dynamic> unsigned = const IMap.empty(),
LocalContent? localContent,
String? transactionId,
String? redactedBy,
String? relatesTo,
String? relationType,
String? replyTo,
String? decryptionError,
String? sendError,
IMap<String, int> reactions = const IMap.empty(),
@JsonKey(name: "last_edit_rowid") int lastEditRowId = 0,
@UnreadTypeConverter() UnreadType? unreadType,
Profile? pmp,
required Content content,
required Content? previousContent,
}) with _$Event {
static String typeJsonFromJson(Map<dynamic, dynamic> json, _) => static String typeJsonFromJson(Map<dynamic, dynamic> json, _) =>
json["decrypted_type"] ?? json["type"]; json["decrypted_type"] ?? json["type"];
@ -25,32 +50,6 @@ abstract class Event with _$Event {
} }
} }
const factory Event({
@JsonKey(name: "rowid") required int rowId,
@JsonKey(name: "timeline_rowid") required int timelineRowId,
required String roomId,
required String eventId,
required String sender,
@JsonKey(readValue: Event.typeJsonFromJson) required String type,
String? stateKey,
@EpochDateTimeConverter() required DateTime timestamp,
@Default(IMap.empty()) IMap<String, dynamic> unsigned,
LocalContent? localContent,
String? transactionId,
String? redactedBy,
String? relatesTo,
String? relationType,
String? replyTo,
String? decryptionError,
String? sendError,
@Default(IMap.empty()) IMap<String, int> reactions,
@JsonKey(name: "last_edit_rowid") @Default(0) int lastEditRowId,
@UnreadTypeConverter() UnreadType? unreadType,
Profile? pmp,
required Content content,
required Content? previousContent,
}) = _Event;
factory Event.fromJson(Map<String, dynamic> json) => factory Event.fromJson(Map<String, dynamic> json) =>
_$EventFromJson(json).copyWith( _$EventFromJson(json).copyWith(
replyTo: replyToFromJson(getContentFromJson(json)), replyTo: replyToFromJson(getContentFromJson(json)),
@ -73,16 +72,14 @@ abstract class Event with _$Event {
} }
@freezed @freezed
abstract class LocalContent with _$LocalContent { sealed class const LocalContent({
const factory LocalContent({ String? sanitizedHtml,
String? sanitizedHtml, String? editSource,
String? editSource, bool? wasPlaintext,
bool? wasPlaintext, bool? bigEmoji,
bool? bigEmoji, bool? hasMath,
bool? hasMath, bool? replyFallbackRemoved,
bool? replyFallbackRemoved, }) with _$LocalContent {
}) = _LocalContent;
factory LocalContent.fromJson(Map<String, Object?> json) => factory LocalContent.fromJson(Map<String, Object?> json) =>
_$LocalContentFromJson(json); _$LocalContentFromJson(json);
} }

View file

@ -1,12 +1,11 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "homeserver.freezed.dart"; part "homeserver.freezed.dart";
@freezed @freezed
abstract class Homeserver with _$Homeserver { sealed class const Homeserver({
const factory Homeserver({ required String name,
required String name, required String description,
required String description, required Uri url,
required Uri url, required String iconUrl,
required String iconUrl, }) with _$Homeserver;
}) = _Homeserver;
}

View file

@ -1,17 +1,15 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/ms_duration.dart"; import "package:nexus/models/ms_duration.dart";
part "audio.freezed.dart"; part "audio.freezed.dart";
part "audio.g.dart"; part "audio.g.dart";
@freezed @freezed
abstract class AudioInfo with _$AudioInfo { sealed class const AudioInfo({
/// Information for images, [size] is in bytes. @MSDuration() Duration? duration,
const factory AudioInfo({ @JsonKey(name: "mimetype") String? mimeType,
@MSDuration() Duration? duration, int? size,
@JsonKey(name: "mimetype") String? mimeType, }) with _$AudioInfo {
int? size,
}) = _AudioInfo;
factory AudioInfo.fromJson(Map<String, Object?> json) => factory AudioInfo.fromJson(Map<String, Object?> json) =>
_$AudioInfoFromJson(json); _$AudioInfoFromJson(json);
} }

View file

@ -1,15 +1,13 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "file.freezed.dart"; part "file.freezed.dart";
part "file.g.dart"; part "file.g.dart";
@freezed @freezed
abstract class FileInfo with _$FileInfo { sealed class const FileInfo({
/// Information for images, [size] is in bytes. @JsonKey(name: "mimetype") String? mimeType,
const factory FileInfo({ int? size,
@JsonKey(name: "mimetype") String? mimeType, }) with _$FileInfo {
int? size,
}) = _FileInfo;
factory FileInfo.fromJson(Map<String, Object?> json) => factory FileInfo.fromJson(Map<String, Object?> json) =>
_$FileInfoFromJson(json); _$FileInfoFromJson(json);
} }

View file

@ -1,18 +1,16 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "image.freezed.dart"; part "image.freezed.dart";
part "image.g.dart"; part "image.g.dart";
@freezed @freezed
abstract class ImageInfo with _$ImageInfo { sealed class const ImageInfo({
/// Information for images, [size] is in bytes. @JsonKey(name: "h") double? height,
const factory ImageInfo({ @JsonKey(name: "w") double? width,
@JsonKey(name: "h") double? height, @JsonKey(name: "mimetype") String? mimeType,
@JsonKey(name: "w") double? width, @JsonKey(name: "xyz.amorgan.blurhash") String? blurHash,
@JsonKey(name: "mimetype") String? mimeType, int? size,
@JsonKey(name: "xyz.amorgan.blurhash") String? blurHash, }) with _$ImageInfo {
int? size,
}) = _ImageInfo;
factory ImageInfo.fromJson(Map<String, Object?> json) => factory ImageInfo.fromJson(Map<String, Object?> json) =>
_$ImageInfoFromJson(json); _$ImageInfoFromJson(json);
} }

View file

@ -1,19 +1,17 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/ms_duration.dart"; import "package:nexus/models/ms_duration.dart";
part "video.freezed.dart"; part "video.freezed.dart";
part "video.g.dart"; part "video.g.dart";
@freezed @freezed
abstract class VideoInfo with _$VideoInfo { sealed class const VideoInfo({
/// Information for images, [size] is in bytes. @JsonKey(name: "h") int? height,
const factory VideoInfo({ @JsonKey(name: "w") int? width,
@JsonKey(name: "h") int? height, @JsonKey(name: "mimetype") String? mimeType,
@JsonKey(name: "w") int? width, @MSDuration() Duration? duration,
@JsonKey(name: "mimetype") String? mimeType, int? size,
@MSDuration() Duration? duration, }) with _$VideoInfo {
int? size,
}) = _VideoInfo;
factory VideoInfo.fromJson(Map<String, Object?> json) => factory VideoInfo.fromJson(Map<String, Object?> json) =>
_$VideoInfoFromJson(json); _$VideoInfoFromJson(json);
} }

View file

@ -1,16 +1,15 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "lazy_load_summary.freezed.dart"; part "lazy_load_summary.freezed.dart";
part "lazy_load_summary.g.dart"; part "lazy_load_summary.g.dart";
@freezed @freezed
abstract class LazyLoadSummary with _$LazyLoadSummary { sealed class const LazyLoadSummary({
const factory LazyLoadSummary({ required IList<String>? heroes,
required IList<String>? heroes, required int? joinedMemberCount,
required int? joinedMemberCount, required int? invitedMemberCount,
required int? invitedMemberCount, }) with _$LazyLoadSummary {
}) = _LazyLoadSummary;
factory LazyLoadSummary.fromJson(Map<String, Object?> json) => factory LazyLoadSummary.fromJson(Map<String, Object?> json) =>
_$LazyLoadSummaryFromJson(json); _$LazyLoadSummaryFromJson(json);
} }

View file

@ -1,15 +1,14 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "oauth_auth_code_response.freezed.dart"; part "oauth_auth_code_response.freezed.dart";
part "oauth_auth_code_response.g.dart"; part "oauth_auth_code_response.g.dart";
@freezed @freezed
abstract class OAuthAuthCodeResponse with _$OAuthAuthCodeResponse { sealed class const OAuthAuthCodeResponse({
const factory OAuthAuthCodeResponse({ required String state,
required String state, required String codeVerifier,
required String codeVerifier, required Uri url,
required Uri url, }) with _$OAuthAuthCodeResponse {
}) = _OAuthAuthCodeResponse;
factory OAuthAuthCodeResponse.fromJson(Map<String, Object?> json) => factory OAuthAuthCodeResponse.fromJson(Map<String, Object?> json) =>
_$OAuthAuthCodeResponseFromJson(json); _$OAuthAuthCodeResponseFromJson(json);
} }

View file

@ -1,17 +1,16 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "open_graph_data.freezed.dart"; part "open_graph_data.freezed.dart";
part "open_graph_data.g.dart"; part "open_graph_data.g.dart";
@freezed @freezed
abstract class OpenGraphData with _$OpenGraphData { sealed class const OpenGraphData({
const factory OpenGraphData({ @JsonKey(name: "og:title") required String? title,
@JsonKey(name: "og:title") required String? title, @JsonKey(name: "og:description") required String? description,
@JsonKey(name: "og:description") required String? description, @JsonKey(name: "og:image") required Uri? imageUrl,
@JsonKey(name: "og:image") required Uri? imageUrl, @JsonKey(name: "og:image:width") required double? width,
@JsonKey(name: "og:image:width") required double? width, @JsonKey(name: "og:image:height") required double? height,
@JsonKey(name: "og:image:height") required double? height, }) with _$OpenGraphData {
}) = _OpenGraphData;
factory OpenGraphData.fromJson(Map<String, dynamic> json) => factory OpenGraphData.fromJson(Map<String, dynamic> json) =>
_$OpenGraphDataFromJson(json); _$OpenGraphDataFromJson(json);
} }

View file

@ -1,17 +1,16 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
part "paginate.freezed.dart"; part "paginate.freezed.dart";
part "paginate.g.dart"; part "paginate.g.dart";
@freezed @freezed
abstract class Paginate with _$Paginate { sealed class const Paginate({
const factory Paginate({ required IList<Event> events,
required IList<Event> events, required IList<Event> relatedEvents,
required IList<Event> relatedEvents, required bool hasMore,
required bool hasMore, }) with _$Paginate {
}) = _Paginate;
factory Paginate.fromJson(Map<String, Object?> json) => factory Paginate.fromJson(Map<String, Object?> json) =>
_$PaginateFromJson(json); _$PaginateFromJson(json);
} }

View file

@ -1,53 +1,44 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/membership.dart"; import "package:nexus/models/content/membership.dart";
part "profile_response.freezed.dart"; part "profile_response.freezed.dart";
part "profile_response.g.dart"; part "profile_response.g.dart";
@freezed @freezed
abstract class ProfileResponse with _$ProfileResponse { sealed class const ProfileResponse({
const factory ProfileResponse({ @JsonKey(fromJson: Profile.fromJson) required Profile profile,
@JsonKey(fromJson: Profile.fromJson) required Profile profile, required Bio? bio,
required Bio? bio, }) with _$ProfileResponse {
}) = _ProfileResponse;
factory ProfileResponse.fromJson(Map<String, Object?> json) => factory ProfileResponse.fromJson(Map<String, Object?> json) =>
_$ProfileResponseFromJson(json); _$ProfileResponseFromJson(json);
} }
@freezed @freezed
abstract class Bio with _$Bio { sealed class const Bio({required String html, String? editSource}) with _$Bio {
const factory Bio({required String html, String? editSource}) = _Bio;
factory Bio.fromJson(Map<String, Object?> json) => _$BioFromJson(json); factory Bio.fromJson(Map<String, Object?> json) => _$BioFromJson(json);
} }
@freezed @freezed
abstract class Profile with _$Profile { sealed class const Profile({
String? id,
String? parseError,
Uri? avatarUrl,
@JsonKey(name: "displayname", fromJson: MembershipContent.displaynameFromJson)
String? displayName,
@JsonKey(readValue: Profile.readTimezone, name: "m.tz") String? timezone,
@JsonKey(readValue: Profile.readPronouns, name: "m.pronouns")
IList<Pronoun> pronouns = const IList.empty(),
}) with _$Profile {
static Object? readPronouns(Map<dynamic, dynamic> map, String key) => static Object? readPronouns(Map<dynamic, dynamic> map, String key) =>
map[key] ?? map["io.fsky.nyx.pronouns"]; map[key] ?? map["io.fsky.nyx.pronouns"];
static Object? readTimezone(Map<dynamic, dynamic> map, String key) => static Object? readTimezone(Map<dynamic, dynamic> map, String key) =>
map[key] ?? map["us.cloke.msc4175.tz"]; map[key] ?? map["us.cloke.msc4175.tz"];
const factory Profile({
String? id,
String? parseError,
Uri? avatarUrl,
@JsonKey(
name: "displayname",
fromJson: MembershipContent.displaynameFromJson,
)
String? displayName,
@JsonKey(readValue: Profile.readTimezone, name: "m.tz") String? timezone,
@Default(IList.empty())
@JsonKey(readValue: Profile.readPronouns, name: "m.pronouns")
IList<Pronoun> pronouns,
}) = _Profile;
factory Profile.fromJson(Map<String, dynamic> json) => factory Profile.fromJson(Map<String, dynamic> json) =>
_$ProfileFromJson(json); _$ProfileFromJson(json);
@ -55,16 +46,14 @@ abstract class Profile with _$Profile {
try { try {
return Profile.fromJson(json); return Profile.fromJson(json);
} catch (error) { } catch (error) {
return Profile(parseError: error.toString()); return _Profile(parseError: error.toString());
} }
} }
} }
@freezed @freezed
abstract class Pronoun with _$Pronoun { sealed class const Pronoun({required String language, required String summary})
const factory Pronoun({required String language, required String summary}) = with _$Pronoun {
_Pronoun;
factory Pronoun.fromJson(Map<String, Object?> json) => factory Pronoun.fromJson(Map<String, Object?> json) =>
_$PronounFromJson(json); _$PronounFromJson(json);
} }

View file

@ -1,18 +1,17 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/epoch_date_time_converter.dart"; import "package:nexus/models/epoch_date_time_converter.dart";
part "read_receipt.freezed.dart"; part "read_receipt.freezed.dart";
part "read_receipt.g.dart"; part "read_receipt.g.dart";
@freezed @freezed
abstract class ReadReceipt with _$ReadReceipt { sealed class const ReadReceipt({
const factory ReadReceipt({ String? roomId,
String? roomId, required String userId,
required String userId, String? threadId,
String? threadId, required String eventId,
required String eventId, @EpochDateTimeConverter() required DateTime timestamp,
@EpochDateTimeConverter() required DateTime timestamp, }) with _$ReadReceipt {
}) = _ReadReceipt;
factory ReadReceipt.fromJson(Map<String, Object?> json) => factory ReadReceipt.fromJson(Map<String, Object?> json) =>
_$ReadReceiptFromJson(json); _$ReadReceiptFromJson(json);
} }

View file

@ -1,16 +1,15 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "download_media.freezed.dart"; part "download_media.freezed.dart";
part "download_media.g.dart"; part "download_media.g.dart";
@freezed @freezed
abstract class DownloadMediaRequest with _$DownloadMediaRequest { sealed class const DownloadMediaRequest({
const factory DownloadMediaRequest({ required Uri mxc,
required Uri mxc, bool encrypted = false,
@Default(false) bool encrypted, bool isAvatar = false,
@Default(false) bool isAvatar, bool thumbnailAvatar = false,
@Default(false) bool thumbnailAvatar, }) with _$DownloadMediaRequest {
}) = _DownloadMediaRequest;
factory DownloadMediaRequest.fromJson(Map<String, Object?> json) => factory DownloadMediaRequest.fromJson(Map<String, Object?> json) =>
_$DownloadMediaRequestFromJson(json); _$DownloadMediaRequestFromJson(json);
} }

View file

@ -1,15 +1,14 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "get_event.freezed.dart"; part "get_event.freezed.dart";
part "get_event.g.dart"; part "get_event.g.dart";
@freezed @freezed
abstract class GetEventRequest with _$GetEventRequest { sealed class const GetEventRequest({
const factory GetEventRequest({ required String roomId,
required String roomId, required String eventId,
required String eventId, bool unredact = false,
@Default(false) bool unredact, }) with _$GetEventRequest {
}) = _GetEventRequest;
factory GetEventRequest.fromJson(Map<String, Object?> json) => factory GetEventRequest.fromJson(Map<String, Object?> json) =>
_$GetEventRequestFromJson(json); _$GetEventRequestFromJson(json);
} }

View file

@ -1,15 +1,14 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "get_related_events.freezed.dart"; part "get_related_events.freezed.dart";
part "get_related_events.g.dart"; part "get_related_events.g.dart";
@freezed @freezed
abstract class GetRelatedEventsRequest with _$GetRelatedEventsRequest { sealed class const GetRelatedEventsRequest({
const factory GetRelatedEventsRequest({ required String roomId,
required String roomId, required String eventId,
required String eventId, required String relationType,
required String relationType, }) with _$GetRelatedEventsRequest {
}) = _GetRelatedEventsRequest;
factory GetRelatedEventsRequest.fromJson(Map<String, Object?> json) => factory GetRelatedEventsRequest.fromJson(Map<String, Object?> json) =>
_$GetRelatedEventsRequestFromJson(json); _$GetRelatedEventsRequestFromJson(json);
} }

View file

@ -1,16 +1,15 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "get_room_state.freezed.dart"; part "get_room_state.freezed.dart";
part "get_room_state.g.dart"; part "get_room_state.g.dart";
@freezed @freezed
abstract class GetRoomStateRequest with _$GetRoomStateRequest { sealed class const GetRoomStateRequest({
const factory GetRoomStateRequest({ required String roomId,
required String roomId, bool refetch = false,
@Default(false) bool refetch, bool fetchMembers = false,
@Default(false) bool fetchMembers, bool includeMembers = false,
@Default(false) bool includeMembers, }) with _$GetRoomStateRequest {
}) = _GetRoomStateRequest;
factory GetRoomStateRequest.fromJson(Map<String, Object?> json) => factory GetRoomStateRequest.fromJson(Map<String, Object?> json) =>
_$GetRoomStateRequestFromJson(json); _$GetRoomStateRequestFromJson(json);
} }

View file

@ -1,15 +1,14 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "join_room.freezed.dart"; part "join_room.freezed.dart";
part "join_room.g.dart"; part "join_room.g.dart";
@freezed @freezed
abstract class JoinRoomRequest with _$JoinRoomRequest { sealed class const JoinRoomRequest({
const factory JoinRoomRequest({ required String roomIdOrAlias,
required String roomIdOrAlias, IList<String> via = const IList.empty(),
@Default(IList.empty()) IList<String> via, }) with _$JoinRoomRequest {
}) = _JoinRoomRequest;
factory JoinRoomRequest.fromJson(Map<String, Object?> json) => factory JoinRoomRequest.fromJson(Map<String, Object?> json) =>
_$JoinRoomRequestFromJson(json); _$JoinRoomRequestFromJson(json);
} }

View file

@ -1,17 +1,16 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "exchange_token.freezed.dart"; part "exchange_token.freezed.dart";
part "exchange_token.g.dart"; part "exchange_token.g.dart";
@freezed @freezed
abstract class OAuthExchangeTokenRequest with _$OAuthExchangeTokenRequest { sealed class const OAuthExchangeTokenRequest({
const factory OAuthExchangeTokenRequest({ required Uri homeserverUrl,
required Uri homeserverUrl, required String codeVerifier,
required String codeVerifier, required Uri redirectUri,
required Uri redirectUri, required String code,
required String code, required String clientId,
required String clientId, }) with _$OAuthExchangeTokenRequest {
}) = _OAuthExchangeTokenRequest;
factory OAuthExchangeTokenRequest.fromJson(Map<String, Object?> json) => factory OAuthExchangeTokenRequest.fromJson(Map<String, Object?> json) =>
_$OAuthExchangeTokenRequestFromJson(json); _$OAuthExchangeTokenRequestFromJson(json);
} }

View file

@ -2,25 +2,24 @@ import "dart:math";
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "get_auth_url.freezed.dart"; part "get_auth_url.freezed.dart";
part "get_auth_url.g.dart"; part "get_auth_url.g.dart";
@freezed @freezed
abstract class OAuthGetAuthUrl with _$OAuthGetAuthUrl { sealed class const OAuthGetAuthUrl({
const factory OAuthGetAuthUrl({ required ResponseMode responseMode,
required ResponseMode responseMode, required Uri homeserverUrl,
required Uri homeserverUrl, required Uri redirectUri,
required Uri redirectUri, required IList<String> scopes,
required IList<String> scopes, required String clientId,
required String clientId, String? userIdHint,
String? userIdHint, }) with _$OAuthGetAuthUrl {
}) = _OAuthGetAuthUrl;
factory OAuthGetAuthUrl.fromJson(Map<String, Object?> json) => factory OAuthGetAuthUrl.fromJson(Map<String, Object?> json) =>
_$OAuthGetAuthUrlFromJson(json); _$OAuthGetAuthUrlFromJson(json);
} }
abstract class Scope { sealed class Scope {
static final openid = "openid"; static final openid = "openid";
static final email = "email"; static final email = "email";
static final clientApi = "urn:matrix:client:api:*"; static final clientApi = "urn:matrix:client:api:*";

View file

@ -1,27 +1,25 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "register_client.freezed.dart"; part "register_client.freezed.dart";
part "register_client.g.dart"; part "register_client.g.dart";
@freezed @freezed
abstract class OAuthRegisterClientRequest with _$OAuthRegisterClientRequest { sealed class const OAuthRegisterClientRequest({
const factory OAuthRegisterClientRequest({ required Uri homeserverUrl,
required Uri homeserverUrl, ApplicationType applicationType = ApplicationType.web,
@Default(ApplicationType.web) ApplicationType applicationType, String? clientName,
String? clientName, required Uri clientUri,
required Uri clientUri, Uri? logoUri,
Uri? logoUri, Uri? policyUri,
Uri? policyUri, Uri? tosUri,
Uri? tosUri, IList<GrantType>? grantTypes,
IList<GrantType>? grantTypes, IList<Uri>? redirectUris,
IList<Uri>? redirectUris, IList<ResponseType>? responseTypes,
IList<ResponseType>? responseTypes,
@Default(AuthMethod.none)
@JsonKey(name: "token_endpoint_auth_method")
AuthMethod? authMethod,
}) = _OAuthRegisterClientRequest;
@JsonKey(name: "token_endpoint_auth_method")
AuthMethod? authMethod = AuthMethod.none,
}) with _$OAuthRegisterClientRequest {
factory OAuthRegisterClientRequest.fromJson(Map<String, Object?> json) => factory OAuthRegisterClientRequest.fromJson(Map<String, Object?> json) =>
_$OAuthRegisterClientRequestFromJson(json); _$OAuthRegisterClientRequestFromJson(json);
} }

View file

@ -1,15 +1,14 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "paginate.freezed.dart"; part "paginate.freezed.dart";
part "paginate.g.dart"; part "paginate.g.dart";
@freezed @freezed
abstract class PaginateRequest with _$PaginateRequest { sealed class const PaginateRequest({
const factory PaginateRequest({ required String roomId,
required String roomId, required int? maxTimelineId,
required int? maxTimelineId, int limit = 20,
@Default(20) int limit, }) with _$PaginateRequest {
}) = _PaginateRequest;
factory PaginateRequest.fromJson(Map<String, Object?> json) => factory PaginateRequest.fromJson(Map<String, Object?> json) =>
_$PaginateRequestFromJson(json); _$PaginateRequestFromJson(json);
} }

View file

@ -1,15 +1,14 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "report.freezed.dart"; part "report.freezed.dart";
part "report.g.dart"; part "report.g.dart";
@freezed @freezed
abstract class ReportRequest with _$ReportRequest { sealed class const ReportRequest({
const factory ReportRequest({ required String roomId,
required String roomId, required String eventId,
required String eventId, String? reason,
String? reason, }) with _$ReportRequest {
}) = _ReportRequest;
factory ReportRequest.fromJson(Map<String, Object?> json) => factory ReportRequest.fromJson(Map<String, Object?> json) =>
_$ReportRequestFromJson(json); _$ReportRequestFromJson(json);
} }

View file

@ -1,20 +1,19 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/content.dart";
part "send_event.freezed.dart"; part "send_event.freezed.dart";
part "send_event.g.dart"; part "send_event.g.dart";
@freezed @freezed
abstract class SendEventRequest with _$SendEventRequest { sealed class const SendEventRequest({
const factory SendEventRequest({ required String roomId,
required String roomId, required String type,
required String type, required Content content,
required Content content, String? relatesTo,
String? relatesTo, String? relationType,
String? relationType, bool synchronous = false,
@Default(false) bool synchronous, bool disableEncryption = false,
@Default(false) bool disableEncryption, }) with _$SendEventRequest {
}) = _SendEventRequest;
factory SendEventRequest.fromJson(Map<String, Object?> json) => factory SendEventRequest.fromJson(Map<String, Object?> json) =>
_$SendEventRequestFromJson(json); _$SendEventRequestFromJson(json);
} }

View file

@ -2,43 +2,36 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/content.dart";
import "package:nexus/models/relation_type.dart"; import "package:nexus/models/relation_type.dart";
part "send_message.freezed.dart"; part "send_message.freezed.dart";
part "send_message.g.dart"; part "send_message.g.dart";
@freezed @freezed
abstract class SendMessageRequest with _$SendMessageRequest { sealed class const SendMessageRequest({
const factory SendMessageRequest({ required String roomId,
required String roomId, required String text,
required String text, Content? baseContent,
Content? baseContent, @JsonKey(name: "mentions") Mentions mentions = const _Mentions(),
@Default(Mentions()) @JsonKey(name: "mentions") Mentions mentions, @JsonKey(name: "relates_to") Relation? relation,
@JsonKey(name: "relates_to") Relation? relation, }) with _$SendMessageRequest {
}) = _SendMessageRequest;
factory SendMessageRequest.fromJson(Map<String, Object?> json) => factory SendMessageRequest.fromJson(Map<String, Object?> json) =>
_$SendMessageRequestFromJson(json); _$SendMessageRequestFromJson(json);
} }
@freezed @freezed
abstract class Mentions with _$Mentions { sealed class const Mentions({
const factory Mentions({ bool room = false,
@Default(false) bool room, IList<String> userIds = const IList.empty(),
@Default(IList.empty()) IList<String> userIds, }) with _$Mentions {
}) = _Mentions;
factory Mentions.fromJson(Map<String, Object?> json) => factory Mentions.fromJson(Map<String, Object?> json) =>
_$MentionsFromJson(json); _$MentionsFromJson(json);
} }
@Freezed(toJson: false) @Freezed(toJson: false)
abstract class Relation with _$Relation { sealed class const Relation({
const Relation._(); required String eventId,
required RelationType relationType,
const factory Relation({ }) with _$Relation {
required String eventId,
required RelationType relationType,
}) = _Relation;
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
switch (relationType) { switch (relationType) {
case RelationType.reply: case RelationType.reply:

View file

@ -1,15 +1,14 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "set_account_data.freezed.dart"; part "set_account_data.freezed.dart";
part "set_account_data.g.dart"; part "set_account_data.g.dart";
@freezed @freezed
abstract class SetAccountDataRequest with _$SetAccountDataRequest { sealed class const SetAccountDataRequest({
const factory SetAccountDataRequest({ required String type,
required String type, required dynamic content,
required dynamic content, String? roomId,
String? roomId, }) with _$SetAccountDataRequest {
}) = _SetAccountDataRequest;
factory SetAccountDataRequest.fromJson(Map<String, Object?> json) => factory SetAccountDataRequest.fromJson(Map<String, Object?> json) =>
_$SetAccountDataRequestFromJson(json); _$SetAccountDataRequestFromJson(json);
} }

View file

@ -1,19 +1,17 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/membership_action.dart"; import "package:nexus/models/membership_action.dart";
part "set_membership.freezed.dart"; part "set_membership.freezed.dart";
part "set_membership.g.dart"; part "set_membership.g.dart";
@freezed @freezed
abstract class SetMembershipRequest with _$SetMembershipRequest { sealed class const SetMembershipRequest({
const factory SetMembershipRequest({ required String userId,
required String userId, required String roomId,
required String roomId, String? reason,
@JsonKey(name: "action") required MembershipAction action,
String? reason, @JsonKey(name: "msc4293_redact_events") bool redact = false,
@JsonKey(name: "action") required MembershipAction action, }) with _$SetMembershipRequest {
@Default(false) @JsonKey(name: "msc4293_redact_events") bool redact,
}) = _SetMembershipRequest;
factory SetMembershipRequest.fromJson(Map<String, Object?> json) => factory SetMembershipRequest.fromJson(Map<String, Object?> json) =>
_$SetMembershipRequestFromJson(json); _$SetMembershipRequestFromJson(json);
} }

View file

@ -1,23 +1,21 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/content.dart";
import "package:nexus/models/ms_duration.dart"; import "package:nexus/models/ms_duration.dart";
part "set_state.freezed.dart"; part "set_state.freezed.dart";
part "set_state.g.dart"; part "set_state.g.dart";
@freezed @freezed
abstract class SetStateRequest with _$SetStateRequest { sealed class const SetStateRequest({
const factory SetStateRequest({ required String roomId,
required String roomId, required String type,
required String type, required String stateKey,
required String stateKey, required Content content,
required Content content,
@JsonKey(name: "delay_ms", includeIfNull: false)
@MSDuration()
@Default(null)
Duration? delay,
}) = _SetStateRequest;
@JsonKey(name: "delay_ms", includeIfNull: false)
@MSDuration()
Duration? delay,
}) with _$SetStateRequest {
factory SetStateRequest.fromJson(Map<String, Object?> json) => factory SetStateRequest.fromJson(Map<String, Object?> json) =>
_$SetStateRequestFromJson(json); _$SetStateRequestFromJson(json);
} }

View file

@ -1,24 +1,23 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
part "upload_media.freezed.dart"; part "upload_media.freezed.dart";
part "upload_media.g.dart"; part "upload_media.g.dart";
@freezed @freezed
abstract class UploadMediaRequest with _$UploadMediaRequest { sealed class const UploadMediaRequest({
const factory UploadMediaRequest({ required String path,
required String path, required bool encrypt,
required bool encrypt, String? filename,
String? filename, @JsonKey(name: "voice_message") bool isVoiceMessage = false,
@Default(false) @JsonKey(name: "voice_message") bool isVoiceMessage, bool forceFile = false,
@Default(false) bool forceFile,
// Below params only work if encodeTo is set
String? encodeTo,
int? resizeWidth,
int? resizeHeight,
int? resizePercent,
@Default(80) int quality,
}) = _UploadMediaRequest;
// Below params only work if encodeTo is set
String? encodeTo,
int? resizeWidth,
int? resizeHeight,
int? resizePercent,
int quality = 80,
}) with _$UploadMediaRequest {
factory UploadMediaRequest.fromJson(Map<String, Object?> json) => factory UploadMediaRequest.fromJson(Map<String, Object?> json) =>
_$UploadMediaRequestFromJson(json); _$UploadMediaRequestFromJson(json);
} }

View file

@ -3,11 +3,37 @@ import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
import "package:nexus/models/read_receipt.dart"; import "package:nexus/models/read_receipt.dart";
import "package:nexus/models/room_metadata.dart"; import "package:nexus/models/room_metadata.dart";
part "room.freezed.dart"; part "room.freezed.dart";
part "room.g.dart"; part "room.g.dart";
@freezed @freezed
abstract class Room with _$Room { sealed class const Room({
@JsonKey(name: "meta") RoomMetadata? metadata,
@JsonKey(fromJson: Room.timelineTupleJsonToIMap)
IMap<int, int?> timeline = const IMap.empty(),
ISet<int> sticky = const ISet.empty(),
@JsonKey(fromJson: Room.eventsJsonToIMap)
IMap<int, Event> events = const IMap.empty(),
bool reset = false,
bool hasFetchedState = false,
bool hasFetchedMembers = false,
IMap<String, IMap<String, int>> state = const IMap.empty(),
IMap<String, IList<ReadReceipt>> receipts = const IMap.empty(),
bool dismissNotifications = false,
bool hasMore = true,
// IMap<String, AccountData> accountData,
// IList<Notification> notifications,
}) with _$Room {
/// [timeline] is an IMap of timelineRowId to eventRowId
/// [events] is an IMap of eventRowId to event
/// [sticky] is an ISet of eventRowId
static IMap<int, int?> timelineTupleJsonToIMap(List<dynamic> json) => static IMap<int, int?> timelineTupleJsonToIMap(List<dynamic> json) =>
IMap.fromEntries( IMap.fromEntries(
json.map( json.map(
@ -26,32 +52,5 @@ abstract class Room with _$Room {
}), }),
); );
/// [timeline] is an IMap of timelineRowId to eventRowId
/// [events] is an IMap of eventRowId to event
/// [sticky] is an ISet of eventRowId
const factory Room({
@JsonKey(name: "meta") RoomMetadata? metadata,
@Default(IMap.empty())
@JsonKey(fromJson: Room.timelineTupleJsonToIMap)
IMap<int, int?> timeline,
@Default(ISet.empty()) ISet<int> sticky,
@Default(IMap.empty())
@JsonKey(fromJson: Room.eventsJsonToIMap)
IMap<int, Event> events,
@Default(false) bool reset,
@Default(false) bool hasFetchedState,
@Default(false) bool hasFetchedMembers,
@Default(IMap.empty()) IMap<String, IMap<String, int>> state,
@Default(IMap.empty()) IMap<String, IList<ReadReceipt>> receipts,
@Default(false) bool dismissNotifications,
@Default(true) bool hasMore,
// required IMap<String, AccountData> accountData,
// required IList<Notification> notifications,
}) = _Room;
factory Room.fromJson(Map<String, Object?> json) => _$RoomFromJson(json); factory Room.fromJson(Map<String, Object?> json) => _$RoomFromJson(json);
} }

View file

@ -1,30 +1,29 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/epoch_date_time_converter.dart"; import "package:nexus/models/epoch_date_time_converter.dart";
import "package:nexus/models/lazy_load_summary.dart"; import "package:nexus/models/lazy_load_summary.dart";
part "room_metadata.freezed.dart"; part "room_metadata.freezed.dart";
part "room_metadata.g.dart"; part "room_metadata.g.dart";
@freezed @freezed
abstract class RoomMetadata with _$RoomMetadata { sealed class const RoomMetadata({
const factory RoomMetadata({ @JsonKey(name: "room_id") required String id,
@JsonKey(name: "room_id") required String id,
// required CreateEventContent creationContent,
// required TombstoneEventContent tombstoneEventContent,
String? name,
Uri? avatar,
String? dmUserId,
String? topic,
String? canonicalAlias,
LazyLoadSummary? lazyLoadSummary,
required bool hasMemberList,
@JsonKey(name: "preview_event_rowid") required int previewEventRowID,
@EpochDateTimeConverter() required DateTime sortingTimestamp,
required int unreadHighlights,
required int unreadNotifications,
required int unreadMessages,
}) = _RoomMetadata;
// CreateEventContent creationContent,
// TombstoneEventContent tombstoneEventContent,
String? name,
Uri? avatar,
String? dmUserId,
String? topic,
String? canonicalAlias,
LazyLoadSummary? lazyLoadSummary,
required bool hasMemberList,
@JsonKey(name: "preview_event_rowid") required int previewEventRowID,
@EpochDateTimeConverter() required DateTime sortingTimestamp,
required int unreadHighlights,
required int unreadNotifications,
required int unreadMessages,
}) with _$RoomMetadata {
factory RoomMetadata.fromJson(Map<String, Object?> json) => factory RoomMetadata.fromJson(Map<String, Object?> json) =>
_$RoomMetadataFromJson(json); _$RoomMetadataFromJson(json);
} }

View file

@ -1,23 +1,22 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/create.dart"; import "package:nexus/models/content/create.dart";
import "package:nexus/models/join_rule.dart"; import "package:nexus/models/join_rule.dart";
part "room_summary.freezed.dart"; part "room_summary.freezed.dart";
part "room_summary.g.dart"; part "room_summary.g.dart";
@freezed @freezed
abstract class RoomSummary with _$RoomSummary { sealed class const RoomSummary({
const factory RoomSummary({ required String roomId,
required String roomId, @JsonKey(name: "num_joined_members") required int joinedMembers,
@JsonKey(name: "num_joined_members") required int joinedMembers, JoinRule? joinRule,
JoinRule? joinRule, String? name,
String? name, Uri? avatarUrl,
Uri? avatarUrl, String? canonicalAlias,
String? canonicalAlias, String? topic,
String? topic, String? roomVersion,
String? roomVersion, @JsonKey(unknownEnumValue: RoomType.room) RoomType? roomType,
@JsonKey(unknownEnumValue: RoomType.room) RoomType? roomType, }) with _$RoomSummary {
}) = _RoomSummary;
factory RoomSummary.fromJson(Map<String, Object?> json) => factory RoomSummary.fromJson(Map<String, Object?> json) =>
_$RoomSummaryFromJson(json); _$RoomSummaryFromJson(json);
} }

View file

@ -1,16 +1,13 @@
import "package:flutter/material.dart"; import "package:material_ui/material_ui.dart";
class Setting { class Setting({
final String title; required final String title,
final String description; required final String description,
final IconData icon; required final IconData icon,
final Widget Function(String title, String description, IconData icon) required final Widget Function(
builder; String title,
String description,
Setting({ IconData icon,
required this.title, )
required this.description, builder,
required this.builder, });
required this.icon,
});
}

Some files were not shown because too many files have changed in this diff Show more