Move to Flutter 3.47, use the improvements that come with this #64

Merged
Henry-Hiles merged 6 commits from flutter-3.47 into main 2026-08-22 13:04:34 -04:00
157 changed files with 1366 additions and 1457 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,19 @@
analyzer: analyzer:
errors: errors:
invalid_annotation_target: ignore invalid_annotation_target: ignore
avoid_print: ignore avoid_print: ignore
exclude: annotate_overrides: ignore
- "build/**" exclude:
- "**/*.g.dart" - "build/**"
- "**/*.freezed.dart" - "**/*.g.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,16 +95,13 @@ 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(
builder: (context, ref, child) => MaterialApp( builder: (context, ref, child) => MaterialApp(
navigatorKey: navigatorKey, navigatorKey: navigatorKey,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
// Use indigo to work around bugs in theme generation
theme: theme:
(ref (ref
.watch(SettingsController.provider) .watch(SettingsController.provider)

View file

@ -1,11 +1,26 @@
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(toJson: false, fromJson: false)
abstract class AccountData with _$AccountData { @JsonSerializable()
const AccountData._(); class const AccountData({
@JsonKey(name: AccountData.invitePermissionConfigKey)
final InvitePermissionConfig invitePermissionConfig =
const InvitePermissionConfig(),
@JsonKey(name: AccountData.directKey)
final IMap<String, IList<String>> directMessages = const IMap.empty(),
@JsonKey(
name: AccountData.recentEmojiKey,
readValue: AccountData.readRecentEmojiValue,
toJson: AccountData.recentEmojiToJson,
)
final 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,44 +34,29 @@ 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({ Map<String, Object?> toJson() => _$AccountDataToJson(this);
@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(toJson: false, fromJson: false)
abstract class InvitePermissionConfig with _$InvitePermissionConfig { @JsonSerializable()
const factory InvitePermissionConfig({ class const InvitePermissionConfig({
@JsonKey(unknownEnumValue: DefaultInviteAction.allow) @JsonKey(unknownEnumValue: DefaultInviteAction.allow)
@Default(DefaultInviteAction.allow) final DefaultInviteAction defaultAction = DefaultInviteAction.allow,
DefaultInviteAction defaultAction, }) with _$InvitePermissionConfig {
}) = _InvitePermissionConfig; Map<String, Object?> toJson() => _$InvitePermissionConfigToJson(this);
factory InvitePermissionConfig.fromJson(Map<String, Object?> json) => factory InvitePermissionConfig.fromJson(Map<String, Object?> json) =>
_$InvitePermissionConfigFromJson(json); _$InvitePermissionConfigFromJson(json);
} }
@freezed @Freezed(toJson: false, fromJson: false)
abstract class RecentEmoji with _$RecentEmoji { @JsonSerializable()
const factory RecentEmoji({required String emoji, required int total}) = class const RecentEmoji({required final String emoji, required final int total})
_RecentEmoji; with _$RecentEmoji {
Map<String, Object?> toJson() => _$RecentEmojiToJson(this);
factory RecentEmoji.fromJson(Map<String, Object?> json) => factory RecentEmoji.fromJson(Map<String, Object?> json) =>
_$RecentEmojiFromJson(json); _$RecentEmojiFromJson(json);

View file

@ -1,16 +1,18 @@
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(toJson: false, fromJson: false)
abstract class ClientState with _$ClientState { @JsonSerializable()
const factory ClientState({ class const ClientState({
required bool isInitialized, required final bool isInitialized,
required bool isLoggedIn, required final bool isLoggedIn,
required bool isVerified, required final bool isVerified,
required String? userId, required final String? userId,
required String? homeserverUrl, required final String? homeserverUrl,
}) = _ClientState; }) with _$ClientState {
Map<String, Object?> toJson() => _$ClientStateToJson(this);
factory ClientState.fromJson(Map<String, Object?> json) => factory ClientState.fromJson(Map<String, Object?> json) =>
_$ClientStateFromJson(json); _$ClientStateFromJson(json);

View file

@ -1,14 +1,16 @@
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(toJson: false, fromJson: false)
abstract class MembersByStatusConfig with _$MembersByStatusConfig { @JsonSerializable()
const factory MembersByStatusConfig({ class const MembersByStatusConfig({
required String roomId, required final String roomId,
required MembershipStatus status, required final MembershipStatus status,
}) = _MembersByStatusConfig; }) with _$MembersByStatusConfig {
Map<String, Object?> toJson() => _$MembersByStatusConfigToJson(this);
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,13 +1,15 @@
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(toJson: false, fromJson: false)
abstract class ReactionsConfig with _$ReactionsConfig { @JsonSerializable()
const factory ReactionsConfig({ class const ReactionsConfig({
required String roomId, required final String roomId,
required int eventRowId, required final int eventRowId,
}) = _ReactionsConfig; }) with _$ReactionsConfig {
Map<String, Object?> toJson() => _$ReactionsConfigToJson(this);
factory ReactionsConfig.fromJson(Map<String, Object?> json) => factory ReactionsConfig.fromJson(Map<String, Object?> json) =>
_$ReactionsConfigFromJson(json); _$ReactionsConfigFromJson(json);

View file

@ -1,11 +1,13 @@
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(toJson: false, fromJson: false)
abstract class UserConfig with _$UserConfig { @JsonSerializable()
const factory UserConfig({required String? roomId, required String userId}) = class const UserConfig({final String? roomId, required final String userId})
_UserConfig; with _$UserConfig {
Map<String, Object?> toJson() => _$UserConfigToJson(this);
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")
@ -30,9 +30,10 @@ enum RoomType {
space, space,
} }
@freezed @Freezed(toJson: false, fromJson: false)
abstract class PreviousRoom with _$PreviousRoom { @JsonSerializable()
const factory PreviousRoom({required String roomId}) = _PreviousRoom; class const PreviousRoom({required final String roomId}) with _$PreviousRoom {
Map<String, Object?> toJson() => _$PreviousRoomToJson(this);
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,
@ -17,12 +17,13 @@ abstract class JoinRulesContent extends Content with _$JoinRulesContent {
_$JoinRulesContentFromJson(json); _$JoinRulesContentFromJson(json);
} }
@freezed @Freezed(toJson: false, fromJson: false)
abstract class AllowCondition with _$AllowCondition { @JsonSerializable()
const factory AllowCondition({ class const AllowCondition({
String? roomId, final String? roomId,
required AllowConditionType type, required final AllowConditionType type,
}) = _AllowCondition; }) with _$AllowCondition {
Map<String, Object?> toJson() => _$AllowConditionToJson(this);
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,
@ -24,12 +24,13 @@ abstract class PowerLevelsContent extends Content with _$PowerLevelsContent {
_$PowerLevelsContentFromJson(json); _$PowerLevelsContentFromJson(json);
} }
@freezed @Freezed(toJson: false, fromJson: false)
abstract class Notifications with _$Notifications { @JsonSerializable()
const factory Notifications({ class const Notifications({
@Default(50) int room, final int room = 50,
@Default(IMapConst({})) IMap<String, int> other, final IMap<String, int> other = const IMap.empty(),
}) = _Notifications; }) with _$Notifications {
Map<String, Object?> toJson() => _$NotificationsToJson(this);
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,
@ -16,24 +17,24 @@ abstract class TopicContent extends Content with _$TopicContent {
_$TopicContentFromJson(json); _$TopicContentFromJson(json);
} }
@freezed @Freezed(toJson: false, fromJson: false)
abstract class TopicContentBlock with _$TopicContentBlock { @JsonSerializable()
factory TopicContentBlock({ class const TopicContentBlock({
@Default(IList.empty()) final IList<TextualRepresentation> representations = const IList.empty(),
@JsonKey(name: "m.text") }) with _$TopicContentBlock {
IList<TextualRepresentation> representations, Map<String, Object?> toJson() => _$TopicContentBlockToJson(this);
}) = _TopicContentBlock;
factory TopicContentBlock.fromJson(Map<String, Object?> json) => factory TopicContentBlock.fromJson(Map<String, Object?> json) =>
_$TopicContentBlockFromJson(json); _$TopicContentBlockFromJson(json);
} }
@freezed @Freezed(toJson: false, fromJson: false)
abstract class TextualRepresentation with _$TextualRepresentation { @JsonSerializable()
factory TextualRepresentation({ class const TextualRepresentation({
required String body, required final String body,
@Default("text/plain") String mimetype, final String mimetype = "text/plain",
}) = _TextualRepresentation; }) with _$TextualRepresentation {
Map<String, Object?> toJson() => _$TextualRepresentationToJson(this);
factory TextualRepresentation.fromJson(Map<String, Object?> json) => factory TextualRepresentation.fromJson(Map<String, Object?> json) =>
_$TextualRepresentationFromJson(json); _$TextualRepresentationFromJson(json);

View file

@ -3,15 +3,16 @@ import "package:freezed_annotation/freezed_annotation.dart";
part "emoji.freezed.dart"; part "emoji.freezed.dart";
part "emoji.g.dart"; part "emoji.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
abstract class Emoji with _$Emoji { @JsonSerializable()
const factory Emoji({ class Emoji({
required String emoji, required final String emoji,
required String category, required final String category,
required IList<String> aliases, required final IList<String> aliases,
required String description, required final String description,
required IList<String> tags, required final IList<String> tags,
}) = _Emoji; }) with _$Emoji {
Map<String, Object?> toJson() => _$EmojiToJson(this);
factory Emoji.fromJson(Map<String, Object?> json) => _$EmojiFromJson(json); factory Emoji.fromJson(Map<String, Object?> json) => _$EmojiFromJson(json);
} }

View file

@ -3,11 +3,39 @@ 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(toJson: false, fromJson: false)
abstract class Event with _$Event { @JsonSerializable()
class const Event({
@JsonKey(name: "rowid") required final int rowId,
@JsonKey(name: "timeline_rowid") required final int timelineRowId,
final String? stateKey,
required final String roomId,
required final String eventId,
required final String sender,
@JsonKey(readValue: Event.typeJsonFromJson) required final String type,
@EpochDateTimeConverter() @override required final DateTime timestamp,
final IMap<String, dynamic> unsigned = const IMap.empty(),
final LocalContent? localContent,
final String? transactionId,
final String? redactedBy,
final String? relatesTo,
final String? relationType,
final String? replyTo,
final String? decryptionError,
final String? sendError,
final IMap<String, int> reactions = const IMap.empty(),
@JsonKey(name: "last_edit_rowid") @override final int lastEditRowId = 0,
@UnreadTypeConverter() @override final UnreadType? unreadType,
final Profile? pmp,
required final Content content,
required final Content? previousContent,
}) with _$Event {
Map<String, Object?> toJson() => _$EventToJson(this);
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 +53,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)),
@ -72,17 +74,19 @@ abstract class Event with _$Event {
); );
} }
@freezed @Freezed(toJson: false, fromJson: false)
abstract class LocalContent with _$LocalContent { @JsonSerializable()
const factory LocalContent({ class const LocalContent({
String? sanitizedHtml, final String? sanitizedHtml,
String? editSource, final String? editSource,
bool? wasPlaintext, final bool? wasPlaintext,
bool? bigEmoji, final bool? bigEmoji,
bool? hasMath, final bool? hasMath,
bool? replyFallbackRemoved, final bool? replyFallbackRemoved,
}) = _LocalContent; }) with _$LocalContent {
Map<String, Object?> toJson() => _$LocalContentToJson(this);
@override
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 { class const Homeserver({
const factory Homeserver({ @override required final String name,
required String name, @override required final String description,
required String description, @override required final Uri url,
required Uri url, @override required final String iconUrl,
required String iconUrl, }) with _$Homeserver;
}) = _Homeserver;
}

View file

@ -1,16 +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 "audio.freezed.dart"; part "audio.freezed.dart";
part "audio.g.dart"; part "audio.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
abstract class AudioInfo with _$AudioInfo { @JsonSerializable()
/// Information for images, [size] is in bytes. class const AudioInfo({
const factory AudioInfo({ @MSDuration() final Duration? duration,
@MSDuration() Duration? duration, @JsonKey(name: "mimetype") final String? mimeType,
@JsonKey(name: "mimetype") String? mimeType, final int? size,
int? size, }) with _$AudioInfo {
}) = _AudioInfo; Map<String, Object?> toJson() => _$AudioInfoToJson(this);
factory AudioInfo.fromJson(Map<String, Object?> json) => factory AudioInfo.fromJson(Map<String, Object?> json) =>
_$AudioInfoFromJson(json); _$AudioInfoFromJson(json);

View file

@ -1,14 +1,15 @@
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(toJson: false, fromJson: false)
abstract class FileInfo with _$FileInfo { @JsonSerializable()
/// Information for images, [size] is in bytes. class const FileInfo({
const factory FileInfo({ @JsonKey(name: "mimetype") final String? mimeType,
@JsonKey(name: "mimetype") String? mimeType, final int? size,
int? size, }) with _$FileInfo {
}) = _FileInfo; Map<String, Object?> toJson() => _$FileInfoToJson(this);
factory FileInfo.fromJson(Map<String, Object?> json) => factory FileInfo.fromJson(Map<String, Object?> json) =>
_$FileInfoFromJson(json); _$FileInfoFromJson(json);

View file

@ -1,17 +1,18 @@
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(toJson: false, fromJson: false)
abstract class ImageInfo with _$ImageInfo { @JsonSerializable()
/// Information for images, [size] is in bytes. class const ImageInfo({
const factory ImageInfo({ @JsonKey(name: "h") final double? height,
@JsonKey(name: "h") double? height, @JsonKey(name: "w") final double? width,
@JsonKey(name: "w") double? width, @JsonKey(name: "mimetype") final String? mimeType,
@JsonKey(name: "mimetype") String? mimeType, @JsonKey(name: "xyz.amorgan.blurhash") final String? blurHash,
@JsonKey(name: "xyz.amorgan.blurhash") String? blurHash, final int? size,
int? size, }) with _$ImageInfo {
}) = _ImageInfo; Map<String, Object?> toJson() => _$ImageInfoToJson(this);
factory ImageInfo.fromJson(Map<String, Object?> json) => factory ImageInfo.fromJson(Map<String, Object?> json) =>
_$ImageInfoFromJson(json); _$ImageInfoFromJson(json);

View file

@ -1,18 +1,19 @@
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(toJson: false, fromJson: false)
abstract class VideoInfo with _$VideoInfo { @JsonSerializable()
/// Information for images, [size] is in bytes. class const VideoInfo({
const factory VideoInfo({ @JsonKey(name: "h") final int? height,
@JsonKey(name: "h") int? height, @JsonKey(name: "w") final int? width,
@JsonKey(name: "w") int? width, @JsonKey(name: "mimetype") final String? mimeType,
@JsonKey(name: "mimetype") String? mimeType, @MSDuration() final Duration? duration,
@MSDuration() Duration? duration, final int? size,
int? size, }) with _$VideoInfo {
}) = _VideoInfo; Map<String, Object?> toJson() => _$VideoInfoToJson(this);
factory VideoInfo.fromJson(Map<String, Object?> json) => factory VideoInfo.fromJson(Map<String, Object?> json) =>
_$VideoInfoFromJson(json); _$VideoInfoFromJson(json);

View file

@ -1,15 +1,17 @@
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(toJson: false, fromJson: false)
abstract class LazyLoadSummary with _$LazyLoadSummary { @JsonSerializable()
const factory LazyLoadSummary({ class const LazyLoadSummary({
required IList<String>? heroes, required final IList<String>? heroes,
required int? joinedMemberCount, required final int? joinedMemberCount,
required int? invitedMemberCount, required final int? invitedMemberCount,
}) = _LazyLoadSummary; }) with _$LazyLoadSummary {
Map<String, Object?> toJson() => _$LazyLoadSummaryToJson(this);
factory LazyLoadSummary.fromJson(Map<String, Object?> json) => factory LazyLoadSummary.fromJson(Map<String, Object?> json) =>
_$LazyLoadSummaryFromJson(json); _$LazyLoadSummaryFromJson(json);

View file

@ -1,14 +1,16 @@
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(toJson: false, fromJson: false)
abstract class OAuthAuthCodeResponse with _$OAuthAuthCodeResponse { @JsonSerializable()
const factory OAuthAuthCodeResponse({ class const OAuthAuthCodeResponse({
required String state, required final String state,
required String codeVerifier, required final String codeVerifier,
required Uri url, required final Uri url,
}) = _OAuthAuthCodeResponse; }) with _$OAuthAuthCodeResponse {
Map<String, Object?> toJson() => _$OAuthAuthCodeResponseToJson(this);
factory OAuthAuthCodeResponse.fromJson(Map<String, Object?> json) => factory OAuthAuthCodeResponse.fromJson(Map<String, Object?> json) =>
_$OAuthAuthCodeResponseFromJson(json); _$OAuthAuthCodeResponseFromJson(json);

View file

@ -1,16 +1,18 @@
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(toJson: false, fromJson: false)
abstract class OpenGraphData with _$OpenGraphData { @JsonSerializable()
const factory OpenGraphData({ class const OpenGraphData({
@JsonKey(name: "og:title") required String? title, @JsonKey(name: "og:title") required final String? title,
@JsonKey(name: "og:description") required String? description, @JsonKey(name: "og:description") required final String? description,
@JsonKey(name: "og:image") required Uri? imageUrl, @JsonKey(name: "og:image") required final Uri? imageUrl,
@JsonKey(name: "og:image:width") required double? width, @JsonKey(name: "og:image:width") required final double? width,
@JsonKey(name: "og:image:height") required double? height, @JsonKey(name: "og:image:height") required final double? height,
}) = _OpenGraphData; }) with _$OpenGraphData {
Map<String, Object?> toJson() => _$OpenGraphDataToJson(this);
factory OpenGraphData.fromJson(Map<String, dynamic> json) => factory OpenGraphData.fromJson(Map<String, dynamic> json) =>
_$OpenGraphDataFromJson(json); _$OpenGraphDataFromJson(json);

View file

@ -1,16 +1,18 @@
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(toJson: false, fromJson: false)
abstract class Paginate with _$Paginate { @JsonSerializable()
const factory Paginate({ class const Paginate({
required IList<Event> events, required final IList<Event> events,
required IList<Event> relatedEvents, required final IList<Event> relatedEvents,
required bool hasMore, required final bool hasMore,
}) = _Paginate; }) with _$Paginate {
Map<String, Object?> toJson() => _$PaginateToJson(this);
factory Paginate.fromJson(Map<String, Object?> json) => factory Paginate.fromJson(Map<String, Object?> json) =>
_$PaginateFromJson(json); _$PaginateFromJson(json);

View file

@ -1,53 +1,55 @@
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(toJson: false, fromJson: false)
abstract class ProfileResponse with _$ProfileResponse { @JsonSerializable()
const factory ProfileResponse({ class const ProfileResponse({
@JsonKey(fromJson: Profile.fromJson) required Profile profile, @JsonKey(fromJson: Profile.fromJson) required final Profile profile,
required Bio? bio, required final Bio? bio,
}) = _ProfileResponse; }) with _$ProfileResponse {
Map<String, Object?> toJson() => _$ProfileResponseToJson(this);
factory ProfileResponse.fromJson(Map<String, Object?> json) => factory ProfileResponse.fromJson(Map<String, Object?> json) =>
_$ProfileResponseFromJson(json); _$ProfileResponseFromJson(json);
} }
@freezed @Freezed(toJson: false, fromJson: false)
abstract class Bio with _$Bio { @JsonSerializable()
const factory Bio({required String html, String? editSource}) = _Bio; class const Bio({required final String html, final String? editSource})
with _$Bio {
Map<String, Object?> toJson() => _$BioToJson(this);
factory Bio.fromJson(Map<String, Object?> json) => _$BioFromJson(json); factory Bio.fromJson(Map<String, Object?> json) => _$BioFromJson(json);
} }
@freezed @Freezed(toJson: false, fromJson: false)
abstract class Profile with _$Profile { @JsonSerializable()
class const Profile({
final String? id,
final String? parseError,
final Uri? avatarUrl,
@JsonKey(name: "displayname", fromJson: MembershipContent.displaynameFromJson)
final String? displayName,
@JsonKey(readValue: Profile.readTimezone, name: "m.tz")
final String? timezone,
@JsonKey(readValue: Profile.readPronouns, name: "m.pronouns")
final IList<Pronoun> pronouns = const IList.empty(),
}) with _$Profile {
Map<String, Object?> toJson() => _$ProfileToJson(this);
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,15 +57,18 @@ 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(toJson: false, fromJson: false)
abstract class Pronoun with _$Pronoun { @JsonSerializable()
const factory Pronoun({required String language, required String summary}) = class const Pronoun({
_Pronoun; required final String language,
required final String summary,
}) with _$Pronoun {
Map<String, Object?> toJson() => _$PronounToJson(this);
factory Pronoun.fromJson(Map<String, Object?> json) => factory Pronoun.fromJson(Map<String, Object?> json) =>
_$PronounFromJson(json); _$PronounFromJson(json);

View file

@ -1,17 +1,19 @@
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(toJson: false, fromJson: false)
abstract class ReadReceipt with _$ReadReceipt { @JsonSerializable()
const factory ReadReceipt({ class const ReadReceipt({
String? roomId, final String? roomId,
required String userId, required final String userId,
String? threadId, final String? threadId,
required String eventId, required final String eventId,
@EpochDateTimeConverter() required DateTime timestamp, @EpochDateTimeConverter() required final DateTime timestamp,
}) = _ReadReceipt; }) with _$ReadReceipt {
Map<String, Object?> toJson() => _$ReadReceiptToJson(this);
factory ReadReceipt.fromJson(Map<String, Object?> json) => factory ReadReceipt.fromJson(Map<String, Object?> json) =>
_$ReadReceiptFromJson(json); _$ReadReceiptFromJson(json);

View file

@ -1,15 +1,17 @@
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(toJson: false, fromJson: false)
abstract class DownloadMediaRequest with _$DownloadMediaRequest { @JsonSerializable()
const factory DownloadMediaRequest({ class const DownloadMediaRequest({
required Uri mxc, required final Uri mxc,
@Default(false) bool encrypted, final bool encrypted = false,
@Default(false) bool isAvatar, final bool isAvatar = false,
@Default(false) bool thumbnailAvatar, final bool thumbnailAvatar = false,
}) = _DownloadMediaRequest; }) with _$DownloadMediaRequest {
Map<String, Object?> toJson() => _$DownloadMediaRequestToJson(this);
factory DownloadMediaRequest.fromJson(Map<String, Object?> json) => factory DownloadMediaRequest.fromJson(Map<String, Object?> json) =>
_$DownloadMediaRequestFromJson(json); _$DownloadMediaRequestFromJson(json);

View file

@ -1,14 +1,16 @@
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(toJson: false, fromJson: false)
abstract class GetEventRequest with _$GetEventRequest { @JsonSerializable()
const factory GetEventRequest({ class const GetEventRequest({
required String roomId, required final String roomId,
required String eventId, required final String eventId,
@Default(false) bool unredact, final bool unredact = false,
}) = _GetEventRequest; }) with _$GetEventRequest {
Map<String, Object?> toJson() => _$GetEventRequestToJson(this);
factory GetEventRequest.fromJson(Map<String, Object?> json) => factory GetEventRequest.fromJson(Map<String, Object?> json) =>
_$GetEventRequestFromJson(json); _$GetEventRequestFromJson(json);

View file

@ -1,14 +1,16 @@
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(toJson: false, fromJson: false)
abstract class GetRelatedEventsRequest with _$GetRelatedEventsRequest { @JsonSerializable()
const factory GetRelatedEventsRequest({ class const GetRelatedEventsRequest({
required String roomId, required final String roomId,
required String eventId, required final String eventId,
required String relationType, required final String relationType,
}) = _GetRelatedEventsRequest; }) with _$GetRelatedEventsRequest {
Map<String, Object?> toJson() => _$GetRelatedEventsRequestToJson(this);
factory GetRelatedEventsRequest.fromJson(Map<String, Object?> json) => factory GetRelatedEventsRequest.fromJson(Map<String, Object?> json) =>
_$GetRelatedEventsRequestFromJson(json); _$GetRelatedEventsRequestFromJson(json);

View file

@ -1,15 +1,17 @@
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(toJson: false, fromJson: false)
abstract class GetRoomStateRequest with _$GetRoomStateRequest { @JsonSerializable()
const factory GetRoomStateRequest({ class const GetRoomStateRequest({
required String roomId, required final String roomId,
@Default(false) bool refetch, final bool refetch = false,
@Default(false) bool fetchMembers, final bool fetchMembers = false,
@Default(false) bool includeMembers, final bool includeMembers = false,
}) = _GetRoomStateRequest; }) with _$GetRoomStateRequest {
Map<String, Object?> toJson() => _$GetRoomStateRequestToJson(this);
factory GetRoomStateRequest.fromJson(Map<String, Object?> json) => factory GetRoomStateRequest.fromJson(Map<String, Object?> json) =>
_$GetRoomStateRequestFromJson(json); _$GetRoomStateRequestFromJson(json);

View file

@ -1,14 +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";
part "join_room.freezed.dart"; part "join_room.freezed.dart";
part "join_room.g.dart"; part "join_room.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
abstract class JoinRoomRequest with _$JoinRoomRequest { @JsonSerializable()
const factory JoinRoomRequest({ class const JoinRoomRequest({
required String roomIdOrAlias, required final String roomIdOrAlias,
@Default(IList.empty()) IList<String> via, final IList<String> via = const IList.empty(),
}) = _JoinRoomRequest; }) with _$JoinRoomRequest {
Map<String, Object?> toJson() => _$JoinRoomRequestToJson(this);
factory JoinRoomRequest.fromJson(Map<String, Object?> json) => factory JoinRoomRequest.fromJson(Map<String, Object?> json) =>
_$JoinRoomRequestFromJson(json); _$JoinRoomRequestFromJson(json);

View file

@ -1,16 +1,18 @@
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(toJson: false, fromJson: false)
abstract class OAuthExchangeTokenRequest with _$OAuthExchangeTokenRequest { @JsonSerializable()
const factory OAuthExchangeTokenRequest({ class const OAuthExchangeTokenRequest({
required Uri homeserverUrl, required final Uri homeserverUrl,
required String codeVerifier, required final String codeVerifier,
required Uri redirectUri, required final Uri redirectUri,
required String code, required final String code,
required String clientId, required final String clientId,
}) = _OAuthExchangeTokenRequest; }) with _$OAuthExchangeTokenRequest {
Map<String, Object?> toJson() => _$OAuthExchangeTokenRequestToJson(this);
factory OAuthExchangeTokenRequest.fromJson(Map<String, Object?> json) => factory OAuthExchangeTokenRequest.fromJson(Map<String, Object?> json) =>
_$OAuthExchangeTokenRequestFromJson(json); _$OAuthExchangeTokenRequestFromJson(json);

View file

@ -2,25 +2,27 @@ 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(toJson: false, fromJson: false)
abstract class OAuthGetAuthUrl with _$OAuthGetAuthUrl { @JsonSerializable()
const factory OAuthGetAuthUrl({ class const OAuthGetAuthUrl({
required ResponseMode responseMode, required final ResponseMode responseMode,
required Uri homeserverUrl, required final Uri homeserverUrl,
required Uri redirectUri, required final Uri redirectUri,
required IList<String> scopes, required final IList<String> scopes,
required String clientId, required final String clientId,
String? userIdHint, final String? userIdHint,
}) = _OAuthGetAuthUrl; }) with _$OAuthGetAuthUrl {
Map<String, Object?> toJson() => _$OAuthGetAuthUrlToJson(this);
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,26 +1,27 @@
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(toJson: false, fromJson: false)
abstract class OAuthRegisterClientRequest with _$OAuthRegisterClientRequest { @JsonSerializable()
const factory OAuthRegisterClientRequest({ class const OAuthRegisterClientRequest({
required Uri homeserverUrl, required final Uri homeserverUrl,
@Default(ApplicationType.web) ApplicationType applicationType, final ApplicationType applicationType = ApplicationType.web,
String? clientName, final String? clientName,
required Uri clientUri, required final Uri clientUri,
Uri? logoUri, final Uri? logoUri,
Uri? policyUri, final Uri? policyUri,
Uri? tosUri, final Uri? tosUri,
IList<GrantType>? grantTypes, final IList<GrantType>? grantTypes,
IList<Uri>? redirectUris, final IList<Uri>? redirectUris,
IList<ResponseType>? responseTypes, final IList<ResponseType>? responseTypes,
@Default(AuthMethod.none) @JsonKey(name: "token_endpoint_auth_method")
@JsonKey(name: "token_endpoint_auth_method") final AuthMethod? authMethod = AuthMethod.none,
AuthMethod? authMethod, }) with _$OAuthRegisterClientRequest {
}) = _OAuthRegisterClientRequest; Map<String, Object?> toJson() => _$OAuthRegisterClientRequestToJson(this);
factory OAuthRegisterClientRequest.fromJson(Map<String, Object?> json) => factory OAuthRegisterClientRequest.fromJson(Map<String, Object?> json) =>
_$OAuthRegisterClientRequestFromJson(json); _$OAuthRegisterClientRequestFromJson(json);

View file

@ -1,14 +1,16 @@
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(toJson: false, fromJson: false)
abstract class PaginateRequest with _$PaginateRequest { @JsonSerializable()
const factory PaginateRequest({ class const PaginateRequest({
required String roomId, required final String roomId,
required int? maxTimelineId, required final int? maxTimelineId,
@Default(20) int limit, final int limit = 20,
}) = _PaginateRequest; }) with _$PaginateRequest {
Map<String, Object?> toJson() => _$PaginateRequestToJson(this);
factory PaginateRequest.fromJson(Map<String, Object?> json) => factory PaginateRequest.fromJson(Map<String, Object?> json) =>
_$PaginateRequestFromJson(json); _$PaginateRequestFromJson(json);

View file

@ -1,14 +1,16 @@
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(toJson: false, fromJson: false)
abstract class ReportRequest with _$ReportRequest { @JsonSerializable()
const factory ReportRequest({ class const ReportRequest({
required String roomId, required final String roomId,
required String eventId, required final String eventId,
String? reason, final String? reason,
}) = _ReportRequest; }) with _$ReportRequest {
Map<String, Object?> toJson() => _$ReportRequestToJson(this);
factory ReportRequest.fromJson(Map<String, Object?> json) => factory ReportRequest.fromJson(Map<String, Object?> json) =>
_$ReportRequestFromJson(json); _$ReportRequestFromJson(json);

View file

@ -1,19 +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";
part "send_event.freezed.dart"; part "send_event.freezed.dart";
part "send_event.g.dart"; part "send_event.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
abstract class SendEventRequest with _$SendEventRequest { @JsonSerializable()
const factory SendEventRequest({ class const SendEventRequest({
required String roomId, required final String roomId,
required String type, required final String type,
required Content content, required final Content content,
String? relatesTo, final String? relatesTo,
String? relationType, final String? relationType,
@Default(false) bool synchronous, final bool synchronous = false,
@Default(false) bool disableEncryption, final bool disableEncryption = false,
}) = _SendEventRequest; }) with _$SendEventRequest {
Map<String, Object?> toJson() => _$SendEventRequestToJson(this);
factory SendEventRequest.fromJson(Map<String, Object?> json) => factory SendEventRequest.fromJson(Map<String, Object?> json) =>
_$SendEventRequestFromJson(json); _$SendEventRequestFromJson(json);

View file

@ -2,43 +2,42 @@ 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(toJson: false, fromJson: false)
abstract class SendMessageRequest with _$SendMessageRequest { @JsonSerializable()
const factory SendMessageRequest({ class const SendMessageRequest({
required String roomId, required final String roomId,
required String text, required final String text,
Content? baseContent, final Content? baseContent,
@Default(Mentions()) @JsonKey(name: "mentions") Mentions mentions, @JsonKey(name: "mentions") final Mentions mentions = const Mentions(),
@JsonKey(name: "relates_to") Relation? relation, @JsonKey(name: "relates_to") final Relation? relation,
}) = _SendMessageRequest; }) with _$SendMessageRequest {
Map<String, Object?> toJson() => _$SendMessageRequestToJson(this);
factory SendMessageRequest.fromJson(Map<String, Object?> json) => factory SendMessageRequest.fromJson(Map<String, Object?> json) =>
_$SendMessageRequestFromJson(json); _$SendMessageRequestFromJson(json);
} }
@freezed @Freezed(toJson: false, fromJson: false)
abstract class Mentions with _$Mentions { @JsonSerializable()
const factory Mentions({ class const Mentions({
@Default(false) bool room, final bool room = false,
@Default(IList.empty()) IList<String> userIds, final IList<String> userIds = const IList.empty(),
}) = _Mentions; }) with _$Mentions {
Map<String, Object?> toJson() => _$MentionsToJson(this);
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 { class const Relation({
const Relation._(); required final String eventId,
required final 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,14 +1,16 @@
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(toJson: false, fromJson: false)
abstract class SetAccountDataRequest with _$SetAccountDataRequest { @JsonSerializable()
const factory SetAccountDataRequest({ class const SetAccountDataRequest({
required String type, required final String type,
required dynamic content, required final dynamic content,
String? roomId, final String? roomId,
}) = _SetAccountDataRequest; }) with _$SetAccountDataRequest {
Map<String, Object?> toJson() => _$SetAccountDataRequestToJson(this);
factory SetAccountDataRequest.fromJson(Map<String, Object?> json) => factory SetAccountDataRequest.fromJson(Map<String, Object?> json) =>
_$SetAccountDataRequestFromJson(json); _$SetAccountDataRequestFromJson(json);

View file

@ -1,18 +1,19 @@
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(toJson: false, fromJson: false)
abstract class SetMembershipRequest with _$SetMembershipRequest { @JsonSerializable()
const factory SetMembershipRequest({ class const SetMembershipRequest({
required String userId, required final String userId,
required String roomId, required final String roomId,
final String? reason,
String? reason, @JsonKey(name: "action") required final MembershipAction action,
@JsonKey(name: "action") required MembershipAction action, @JsonKey(name: "msc4293_redact_events") final bool redact = false,
@Default(false) @JsonKey(name: "msc4293_redact_events") bool redact, }) with _$SetMembershipRequest {
}) = _SetMembershipRequest; Map<String, Object?> toJson() => _$SetMembershipRequestToJson(this);
factory SetMembershipRequest.fromJson(Map<String, Object?> json) => factory SetMembershipRequest.fromJson(Map<String, Object?> json) =>
_$SetMembershipRequestFromJson(json); _$SetMembershipRequestFromJson(json);

View file

@ -1,22 +1,23 @@
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(toJson: false, fromJson: false)
abstract class SetStateRequest with _$SetStateRequest { @JsonSerializable()
const factory SetStateRequest({ class const SetStateRequest({
required String roomId, required final String roomId,
required String type, required final String type,
required String stateKey, required final String stateKey,
required Content content, required final Content content,
@JsonKey(name: "delay_ms", includeIfNull: false) @JsonKey(name: "delay_ms", includeIfNull: false)
@MSDuration() @MSDuration()
@Default(null) final Duration? delay,
Duration? delay, }) with _$SetStateRequest {
}) = _SetStateRequest; Map<String, Object?> toJson() => _$SetStateRequestToJson(this);
factory SetStateRequest.fromJson(Map<String, Object?> json) => factory SetStateRequest.fromJson(Map<String, Object?> json) =>
_$SetStateRequestFromJson(json); _$SetStateRequestFromJson(json);

View file

@ -1,23 +1,26 @@
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(toJson: false, fromJson: false)
abstract class UploadMediaRequest with _$UploadMediaRequest { @JsonSerializable()
const factory UploadMediaRequest({ class const UploadMediaRequest({
required String path, required final String path,
required bool encrypt, required final bool encrypt,
String? filename, final String? filename,
@Default(false) @JsonKey(name: "voice_message") bool isVoiceMessage, @JsonKey(name: "voice_message") final bool isVoiceMessage = false,
@Default(false) bool forceFile, final bool forceFile = false,
final
// Below params only work if encodeTo is set // Below params only work if encodeTo is set
String? encodeTo, String?
int? resizeWidth, encodeTo,
int? resizeHeight, final int? resizeWidth,
int? resizePercent, final int? resizeHeight,
@Default(80) int quality, final int? resizePercent,
}) = _UploadMediaRequest; final int quality = 80,
}) with _$UploadMediaRequest {
Map<String, Object?> toJson() => _$UploadMediaRequestToJson(this);
factory UploadMediaRequest.fromJson(Map<String, Object?> json) => factory UploadMediaRequest.fromJson(Map<String, Object?> json) =>
_$UploadMediaRequestFromJson(json); _$UploadMediaRequestFromJson(json);

View file

@ -3,11 +3,38 @@ 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(toJson: false, fromJson: false)
abstract class Room with _$Room { @JsonSerializable()
class const Room({
@JsonKey(name: "meta") final RoomMetadata? metadata,
@JsonKey(fromJson: Room.timelineTupleJsonToIMap)
final IMap<int, int?> timeline = const IMap.empty(),
final ISet<int> sticky = const ISet.empty(),
@JsonKey(fromJson: Room.eventsJsonToIMap)
final IMap<int, Event> events = const IMap.empty(),
final bool reset = false,
final bool hasFetchedState = false,
final bool hasFetchedMembers = false,
final IMap<String, IMap<String, int>> state = const IMap.empty(),
final IMap<String, IList<ReadReceipt>> receipts = const IMap.empty(),
final bool dismissNotifications = false,
final 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 +53,7 @@ abstract class Room with _$Room {
}), }),
); );
/// [timeline] is an IMap of timelineRowId to eventRowId Map<String, Object?> toJson() => _$RoomToJson(this);
/// [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,29 +1,31 @@
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(toJson: false, fromJson: false)
abstract class RoomMetadata with _$RoomMetadata { @JsonSerializable()
const factory RoomMetadata({ class const RoomMetadata({
@JsonKey(name: "room_id") required String id, @JsonKey(name: "room_id") required final String id,
// required CreateEventContent creationContent, // CreateEventContent creationContent,
// required TombstoneEventContent tombstoneEventContent, // TombstoneEventContent tombstoneEventContent,
String? name, final String? name,
Uri? avatar, final Uri? avatar,
String? dmUserId, final String? dmUserId,
String? topic, final String? topic,
String? canonicalAlias, final String? canonicalAlias,
LazyLoadSummary? lazyLoadSummary, final LazyLoadSummary? lazyLoadSummary,
required bool hasMemberList, required final bool hasMemberList,
@JsonKey(name: "preview_event_rowid") required int previewEventRowID, @JsonKey(name: "preview_event_rowid") required final int previewEventRowID,
@EpochDateTimeConverter() required DateTime sortingTimestamp, @EpochDateTimeConverter() required final DateTime sortingTimestamp,
required int unreadHighlights, required final int unreadHighlights,
required int unreadNotifications, required final int unreadNotifications,
required int unreadMessages, required final int unreadMessages,
}) = _RoomMetadata; }) with _$RoomMetadata {
Map<String, Object?> toJson() => _$RoomMetadataToJson(this);
factory RoomMetadata.fromJson(Map<String, Object?> json) => factory RoomMetadata.fromJson(Map<String, Object?> json) =>
_$RoomMetadataFromJson(json); _$RoomMetadataFromJson(json);

View file

@ -1,22 +1,24 @@
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(toJson: false, fromJson: false)
abstract class RoomSummary with _$RoomSummary { @JsonSerializable()
const factory RoomSummary({ class const RoomSummary({
required String roomId, required final String roomId,
@JsonKey(name: "num_joined_members") required int joinedMembers, @JsonKey(name: "num_joined_members") required final int joinedMembers,
JoinRule? joinRule, final JoinRule? joinRule,
String? name, final String? name,
Uri? avatarUrl, final Uri? avatarUrl,
String? canonicalAlias, final String? canonicalAlias,
String? topic, final String? topic,
String? roomVersion, final String? roomVersion,
@JsonKey(unknownEnumValue: RoomType.room) RoomType? roomType, @JsonKey(unknownEnumValue: RoomType.room) final RoomType? roomType,
}) = _RoomSummary; }) with _$RoomSummary {
Map<String, Object?> toJson() => _$RoomSummaryToJson(this);
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