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

Reviewed-on: #64
This commit is contained in:
Henry Hiles 2026-08-22 13:04:33 -04:00 committed by Henry Hiles
commit 077044ec19
157 changed files with 1366 additions and 1457 deletions

View file

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

View file

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

View file

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

View file

@ -1,12 +1,19 @@
analyzer:
errors:
invalid_annotation_target: ignore
avoid_print: ignore
exclude:
- "build/**"
- "**/*.g.dart"
- "**/*.freezed.dart"
errors:
invalid_annotation_target: ignore
avoid_print: ignore
annotate_overrides: ignore
exclude:
- "build/**"
- "**/*.g.dart"
- "**/*.freezed.dart"
- android/**
- ios/**
- web/**
- windows/**
- macos/**
- linux/**
include: package:flutter_lints/flutter.yaml
linter:
rules:
prefer_double_quotes: true
rules:
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
zipStoreBase=GRADLE_USER_HOME
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": {
"locked": {
"lastModified": 1785967620,
"narHash": "sha256-IItrdb7Puk05RqOBWZYFC5X6Wl1sJmCfh5MWVHw5iMM=",
"lastModified": 1786862985,
"narHash": "sha256-FBJRXmbGXiSUDvYEbfLYRkckayyZ6SK1UEqhCrIZ2Cs=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "b7c2ada94fe99c15b0dbcf4d11fd7850b957a436",
"rev": "e5bdc4a41d4c072fe1e3787eaa0320a384741d44",
"type": "github"
},
"original": {

View file

@ -6,10 +6,8 @@ import "package:nexus/models/content/content.dart";
import "package:nexus/models/content/message.dart";
import "package:path/path.dart";
class AttachmentController extends Notifier<(String, MessageContent?)?> {
final String roomId;
AttachmentController(this.roomId);
class AttachmentController(final String roomId)
extends Notifier<(String, MessageContent?)?> {
@override
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/requests/oauth/get_auth_url.dart";
class AuthUrlController extends AsyncNotifier<OAuthAuthCodeResponse> {
final Uri homeserver;
AuthUrlController(this.homeserver);
class AuthUrlController(final Uri homeserver)
extends AsyncNotifier<OAuthAuthCodeResponse> {
@override
Future<OAuthAuthCodeResponse> build() async => ref
.watch(ClientController.provider.notifier)

View file

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

View file

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

View file

@ -1,7 +1,7 @@
import "dart:convert";
import "package:emoji_text_field/models/emoji_category.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:http/http.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/requests/get_event.dart";
class EventController extends AsyncNotifier<Event?> {
final GetEventRequest request;
EventController(this.request);
class EventController(final GetEventRequest request)
extends AsyncNotifier<Event?> {
@override
Future<Event?> build() async {
final room = ref.watch(

View file

@ -1,10 +1,7 @@
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/shared_prefs.dart";
class KeyController extends Notifier<String?> {
final String key;
KeyController(this.key);
class KeyController(final String key) extends Notifier<String?> {
static const String spaceKey = "space";
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/requests/get_room_state.dart";
class MembersController extends AsyncNotifier<ISet<Event>> {
final String roomId;
MembersController(this.roomId);
class MembersController(final String roomId)
extends AsyncNotifier<ISet<Event>> {
@override
Future<ISet<Event>> build() async {
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/event.dart";
class MembersByStatusController extends AsyncNotifier<ISet<Event>> {
final MembersByStatusConfig config;
MembersByStatusController(this.config);
class MembersByStatusController(final MembersByStatusConfig config)
extends AsyncNotifier<ISet<Event>> {
@override
Future<ISet<Event>> build() => ref.watch(
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/event.dart";
class MembersGroupedController
class MembersGroupedController(final MembersByStatusConfig config)
extends AsyncNotifier<IList<MapEntry<int?, ISet<Event>>>> {
final MembersByStatusConfig config;
MembersGroupedController(this.config);
@override
Future<IList<MapEntry<int?, ISet<Event>>>> build() async {
final room = ref.watch(

View file

@ -1,11 +1,10 @@
import "dart:async";
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
class MultiProviderController extends AsyncNotifier<void> {
MultiProviderController(this.providers);
final IList<AsyncNotifierProvider> providers;
class MultiProviderController(final IList<AsyncNotifierProvider> providers)
extends AsyncNotifier<void> {
@override
Future<void> build() =>
.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/models/event.dart";
class PinnedEventsController extends AsyncNotifier<IList<Event>> {
final String roomId;
PinnedEventsController(this.roomId);
class PinnedEventsController(final String roomId)
extends AsyncNotifier<IList<Event>> {
@override
Future<IList<Event>> build() async {
final pinIds = ref.watch(PinnedIdsController.provider(roomId));
@ -15,9 +13,8 @@ class PinnedEventsController extends AsyncNotifier<IList<Event>> {
return (await Future.wait(
pinIds.map(
(eventId) => ref.watch(
EventController.provider(
.new(eventId: eventId, roomId: roomId),
).future,
EventController.provider(.new(eventId: eventId, roomId: roomId))
.future,
),
),
)).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/pinned_events.dart";
class PinnedIdsController extends Notifier<IList<String>> {
final String roomId;
PinnedIdsController(this.roomId);
class PinnedIdsController(final String roomId) extends Notifier<IList<String>> {
@override
IList<String> build() {
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/power_levels.dart";
class PowerLevelController extends Notifier<bool> {
final PowerLevelConfig config;
PowerLevelController(this.config);
class PowerLevelController(final PowerLevelConfig config)
extends Notifier<bool> {
@override
bool build() {
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/models/profile_response.dart";
class ProfileController extends AsyncNotifier<ProfileResponse> {
final String userId;
ProfileController(this.userId);
class ProfileController(final String userId)
extends AsyncNotifier<ProfileResponse> {
@override
Future<ProfileResponse> build() {
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/content/reaction.dart";
class ReactionsController extends AsyncNotifier<IMap<String, IList<String>>> {
final ReactionsConfig config;
ReactionsController(this.config);
class ReactionsController(final ReactionsConfig config)
extends AsyncNotifier<IMap<String, IList<String>>> {
@override
Future<IMap<String, IList<String>>> build() async {
final eventInfo = ref.watch(

View file

@ -1,5 +1,6 @@
import "dart:async";
import "dart:math";
import "package:collection/collection.dart";
import "package:fast_immutable_collections/fast_immutable_collections.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/room.dart";
class RoomChatController extends AsyncNotifier<IList<Event>?> {
final String roomId;
RoomChatController(this.roomId);
class RoomChatController(final String roomId)
extends AsyncNotifier<IList<Event>?> {
@override
Future<IList<Event>?> build() async {
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/room.dart";
class RoomCreatorsController extends Notifier<IList<String>> {
final Room room;
RoomCreatorsController(this.room);
class RoomCreatorsController(final Room room) extends Notifier<IList<String>> {
@override
IList<String> build() {
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/room_summary.dart";
class RoomSummaryController extends AsyncNotifier<RoomSummary> {
final JoinRoomRequest request;
RoomSummaryController(this.request);
class RoomSummaryController(final JoinRoomRequest request)
extends AsyncNotifier<RoomSummary> {
@override
Future<RoomSummary> build() =>
ref.watch(ClientController.provider.notifier).getRoomSummary(request);

View file

@ -1,6 +1,6 @@
import "dart:io";
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:intl/intl.dart";
import "package:m3e_buttons/m3e_buttons.dart";

View file

@ -1,6 +1,6 @@
import "package:collection/collection.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:nexus/controllers/account_data.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/models/open_graph_data.dart";
class UrlPreviewController extends AsyncNotifier<OpenGraphData?> {
final Uri url;
UrlPreviewController(this.url);
class UrlPreviewController(final Uri url)
extends AsyncNotifier<OpenGraphData?> {
@override
Future<OpenGraphData?> build() async {
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/room.dart";
class ViaController extends Notifier<String> {
final Room room;
ViaController(this.room);
class ViaController(final Room room) extends Notifier<String> {
@override
String build() {
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 {
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:hooks_riverpod/hooks_riverpod.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 {
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/widgets/user_bottom_sheet.dart";

View file

@ -1,5 +1,5 @@
import "package:color_hash/color_hash.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
extension ToColor on String {
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:url_launcher/url_launcher.dart" as ul;
class LaunchHelper {
final Ref ref;
LaunchHelper(this.ref);
class LaunchHelper(Ref ref) {
Future<bool> launchUrl(Uri url, {bool useWebview = false}) async {
try {
return await ul.launchUrl(

View file

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

View file

@ -1,4 +1,5 @@
import "dart:io";
import "package:dynamic_color/dynamic_color.dart";
import "package:fast_immutable_collections/fast_immutable_collections.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/loading.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>();
@ -94,16 +95,13 @@ void main() async {
);
}
class App extends StatelessWidget {
const App({super.key});
class const App({super.key}) extends StatelessWidget {
@override
Widget build(BuildContext context) => DynamicColorBuilder(
builder: (lightDynamic, darkDynamic) => Consumer(
builder: (context, ref, child) => MaterialApp(
navigatorKey: navigatorKey,
debugShowCheckedModeBanner: false,
// Use indigo to work around bugs in theme generation
theme:
(ref
.watch(SettingsController.provider)

View file

@ -1,11 +1,26 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart";
part "account_data.freezed.dart";
part "account_data.g.dart";
@freezed
abstract class AccountData with _$AccountData {
const AccountData._();
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
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(
Map<dynamic, dynamic> json,
String key,
@ -19,44 +34,29 @@ abstract class AccountData with _$AccountData {
static const directKey = "m.direct";
static const recentEmojiKey = "m.recent_emoji";
const factory AccountData({
@JsonKey(name: AccountData.invitePermissionConfigKey)
@Default(InvitePermissionConfig())
InvitePermissionConfig invitePermissionConfig,
@JsonKey(name: AccountData.directKey)
@Default(IMap.empty())
IMap<String, IList<String>> directMessages,
@JsonKey(
name: AccountData.recentEmojiKey,
readValue: AccountData.readRecentEmojiValue,
toJson: AccountData.recentEmojiToJson,
)
@Default(IList.empty())
IList<RecentEmoji> recentEmoji,
}) = _AccountData;
Map<String, Object?> toJson() => _$AccountDataToJson(this);
factory AccountData.fromJson(Map<String, Object?> json) =>
_$AccountDataFromJson(json);
}
@freezed
abstract class InvitePermissionConfig with _$InvitePermissionConfig {
const factory InvitePermissionConfig({
@JsonKey(unknownEnumValue: DefaultInviteAction.allow)
@Default(DefaultInviteAction.allow)
DefaultInviteAction defaultAction,
}) = _InvitePermissionConfig;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const InvitePermissionConfig({
@JsonKey(unknownEnumValue: DefaultInviteAction.allow)
final DefaultInviteAction defaultAction = DefaultInviteAction.allow,
}) with _$InvitePermissionConfig {
Map<String, Object?> toJson() => _$InvitePermissionConfigToJson(this);
factory InvitePermissionConfig.fromJson(Map<String, Object?> json) =>
_$InvitePermissionConfigFromJson(json);
}
@freezed
abstract class RecentEmoji with _$RecentEmoji {
const factory RecentEmoji({required String emoji, required int total}) =
_RecentEmoji;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const RecentEmoji({required final String emoji, required final int total})
with _$RecentEmoji {
Map<String, Object?> toJson() => _$RecentEmojiToJson(this);
factory RecentEmoji.fromJson(Map<String, Object?> json) =>
_$RecentEmojiFromJson(json);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -19,9 +19,11 @@ import "package:nexus/models/content/history_visibility.dart";
class Content {
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() => {};
static Map<String, dynamic> readValue(Map<dynamic, dynamic> json, _) =>
@ -34,13 +36,16 @@ class Content {
?.contentFromJson ??
Content.fromJson)(json);
} catch (error) {
if (error is Error) return .new(parseError: error);
if (error is Error) return Content(parseError: error);
rethrow;
}
}
}
enum EventType {
enum EventType(
final String type,
final Content Function(Map<String, dynamic> json) contentFromJson,
) {
encrypted("m.room.encrypted", EncryptedContent.fromJson),
redaction("m.room.redaction", RedactionContent.fromJson),
encryption("m.room.encryption", EncryptionContent.fromJson),
@ -61,8 +66,4 @@ enum EventType {
reaction("m.reaction", ReactionContent.fromJson),
pinnedEvents("m.room.pinned_events", PinnedEventsContent.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";
@freezed
abstract class CreateContent extends Content with _$CreateContent {
sealed class CreateContent extends Content with _$CreateContent {
CreateContent._();
factory CreateContent({
@JsonKey(name: "additional_creators")
@ -30,9 +30,10 @@ enum RoomType {
space,
}
@freezed
abstract class PreviousRoom with _$PreviousRoom {
const factory PreviousRoom({required String roomId}) = _PreviousRoom;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const PreviousRoom({required final String roomId}) with _$PreviousRoom {
Map<String, Object?> toJson() => _$PreviousRoomToJson(this);
factory PreviousRoom.fromJson(Map<String, Object?> json) =>
_$PreviousRoomFromJson(json);

View file

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

View file

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

View file

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

View file

@ -6,7 +6,7 @@ part "join_rules.freezed.dart";
part "join_rules.g.dart";
@freezed
abstract class JoinRulesContent extends Content with _$JoinRulesContent {
sealed class JoinRulesContent extends Content with _$JoinRulesContent {
JoinRulesContent._();
factory JoinRulesContent({
required JoinRule joinRule,
@ -17,12 +17,13 @@ abstract class JoinRulesContent extends Content with _$JoinRulesContent {
_$JoinRulesContentFromJson(json);
}
@freezed
abstract class AllowCondition with _$AllowCondition {
const factory AllowCondition({
String? roomId,
required AllowConditionType type,
}) = _AllowCondition;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const AllowCondition({
final String? roomId,
required final AllowConditionType type,
}) with _$AllowCondition {
Map<String, Object?> toJson() => _$AllowConditionToJson(this);
factory AllowCondition.fromJson(Map<String, Object?> json) =>
_$AllowConditionFromJson(json);

View file

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

View file

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

View file

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

View file

@ -5,7 +5,7 @@ part "pinned_events.freezed.dart";
part "pinned_events.g.dart";
@freezed
abstract class PinnedEventsContent extends Content with _$PinnedEventsContent {
sealed class PinnedEventsContent extends Content with _$PinnedEventsContent {
PinnedEventsContent._();
factory PinnedEventsContent({
@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";
@freezed
abstract class PowerLevelsContent extends Content with _$PowerLevelsContent {
sealed class PowerLevelsContent extends Content with _$PowerLevelsContent {
PowerLevelsContent._();
factory PowerLevelsContent({
@Default(IMap.empty()) IMap<String, int> events,
@ -24,12 +24,13 @@ abstract class PowerLevelsContent extends Content with _$PowerLevelsContent {
_$PowerLevelsContentFromJson(json);
}
@freezed
abstract class Notifications with _$Notifications {
const factory Notifications({
@Default(50) int room,
@Default(IMapConst({})) IMap<String, int> other,
}) = _Notifications;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const Notifications({
final int room = 50,
final IMap<String, int> other = const IMap.empty(),
}) with _$Notifications {
Map<String, Object?> toJson() => _$NotificationsToJson(this);
factory Notifications.fromJson(Map<String, Object?> json) =>
_$NotificationsFromJson(json);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,15 +3,16 @@ import "package:freezed_annotation/freezed_annotation.dart";
part "emoji.freezed.dart";
part "emoji.g.dart";
@freezed
abstract class Emoji with _$Emoji {
const factory Emoji({
required String emoji,
required String category,
required IList<String> aliases,
required String description,
required IList<String> tags,
}) = _Emoji;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class Emoji({
required final String emoji,
required final String category,
required final IList<String> aliases,
required final String description,
required final IList<String> tags,
}) with _$Emoji {
Map<String, Object?> toJson() => _$EmojiToJson(this);
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/epoch_date_time_converter.dart";
import "package:nexus/models/profile_response.dart";
part "event.freezed.dart";
part "event.g.dart";
@freezed
abstract class Event with _$Event {
@Freezed(toJson: false, fromJson: false)
@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, _) =>
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) =>
_$EventFromJson(json).copyWith(
replyTo: replyToFromJson(getContentFromJson(json)),
@ -72,17 +74,19 @@ abstract class Event with _$Event {
);
}
@freezed
abstract class LocalContent with _$LocalContent {
const factory LocalContent({
String? sanitizedHtml,
String? editSource,
bool? wasPlaintext,
bool? bigEmoji,
bool? hasMath,
bool? replyFallbackRemoved,
}) = _LocalContent;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const LocalContent({
final String? sanitizedHtml,
final String? editSource,
final bool? wasPlaintext,
final bool? bigEmoji,
final bool? hasMath,
final bool? replyFallbackRemoved,
}) with _$LocalContent {
Map<String, Object?> toJson() => _$LocalContentToJson(this);
@override
factory LocalContent.fromJson(Map<String, Object?> json) =>
_$LocalContentFromJson(json);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,53 +1,55 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/membership.dart";
part "profile_response.freezed.dart";
part "profile_response.g.dart";
@freezed
abstract class ProfileResponse with _$ProfileResponse {
const factory ProfileResponse({
@JsonKey(fromJson: Profile.fromJson) required Profile profile,
required Bio? bio,
}) = _ProfileResponse;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const ProfileResponse({
@JsonKey(fromJson: Profile.fromJson) required final Profile profile,
required final Bio? bio,
}) with _$ProfileResponse {
Map<String, Object?> toJson() => _$ProfileResponseToJson(this);
factory ProfileResponse.fromJson(Map<String, Object?> json) =>
_$ProfileResponseFromJson(json);
}
@freezed
abstract class Bio with _$Bio {
const factory Bio({required String html, String? editSource}) = _Bio;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
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);
}
@freezed
abstract class Profile with _$Profile {
@Freezed(toJson: false, fromJson: false)
@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) =>
map[key] ?? map["io.fsky.nyx.pronouns"];
static Object? readTimezone(Map<dynamic, dynamic> map, String key) =>
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) =>
_$ProfileFromJson(json);
@ -55,15 +57,18 @@ abstract class Profile with _$Profile {
try {
return Profile.fromJson(json);
} catch (error) {
return Profile(parseError: error.toString());
return _Profile(parseError: error.toString());
}
}
}
@freezed
abstract class Pronoun with _$Pronoun {
const factory Pronoun({required String language, required String summary}) =
_Pronoun;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const Pronoun({
required final String language,
required final String summary,
}) with _$Pronoun {
Map<String, Object?> toJson() => _$PronounToJson(this);
factory Pronoun.fromJson(Map<String, Object?> json) =>
_$PronounFromJson(json);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,19 +1,21 @@
import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/content.dart";
part "send_event.freezed.dart";
part "send_event.g.dart";
@freezed
abstract class SendEventRequest with _$SendEventRequest {
const factory SendEventRequest({
required String roomId,
required String type,
required Content content,
String? relatesTo,
String? relationType,
@Default(false) bool synchronous,
@Default(false) bool disableEncryption,
}) = _SendEventRequest;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const SendEventRequest({
required final String roomId,
required final String type,
required final Content content,
final String? relatesTo,
final String? relationType,
final bool synchronous = false,
final bool disableEncryption = false,
}) with _$SendEventRequest {
Map<String, Object?> toJson() => _$SendEventRequestToJson(this);
factory SendEventRequest.fromJson(Map<String, Object?> 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:nexus/models/content/content.dart";
import "package:nexus/models/relation_type.dart";
part "send_message.freezed.dart";
part "send_message.g.dart";
@freezed
abstract class SendMessageRequest with _$SendMessageRequest {
const factory SendMessageRequest({
required String roomId,
required String text,
Content? baseContent,
@Default(Mentions()) @JsonKey(name: "mentions") Mentions mentions,
@JsonKey(name: "relates_to") Relation? relation,
}) = _SendMessageRequest;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const SendMessageRequest({
required final String roomId,
required final String text,
final Content? baseContent,
@JsonKey(name: "mentions") final Mentions mentions = const Mentions(),
@JsonKey(name: "relates_to") final Relation? relation,
}) with _$SendMessageRequest {
Map<String, Object?> toJson() => _$SendMessageRequestToJson(this);
factory SendMessageRequest.fromJson(Map<String, Object?> json) =>
_$SendMessageRequestFromJson(json);
}
@freezed
abstract class Mentions with _$Mentions {
const factory Mentions({
@Default(false) bool room,
@Default(IList.empty()) IList<String> userIds,
}) = _Mentions;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const Mentions({
final bool room = false,
final IList<String> userIds = const IList.empty(),
}) with _$Mentions {
Map<String, Object?> toJson() => _$MentionsToJson(this);
factory Mentions.fromJson(Map<String, Object?> json) =>
_$MentionsFromJson(json);
}
@Freezed(toJson: false)
abstract class Relation with _$Relation {
const Relation._();
const factory Relation({
required String eventId,
required RelationType relationType,
}) = _Relation;
class const Relation({
required final String eventId,
required final RelationType relationType,
}) with _$Relation {
Map<String, dynamic> toJson() {
switch (relationType) {
case RelationType.reply:

View file

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

View file

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

View file

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

View file

@ -1,23 +1,26 @@
import "package:freezed_annotation/freezed_annotation.dart";
part "upload_media.freezed.dart";
part "upload_media.g.dart";
@freezed
abstract class UploadMediaRequest with _$UploadMediaRequest {
const factory UploadMediaRequest({
required String path,
required bool encrypt,
String? filename,
@Default(false) @JsonKey(name: "voice_message") bool isVoiceMessage,
@Default(false) bool forceFile,
// Below params only work if encodeTo is set
String? encodeTo,
int? resizeWidth,
int? resizeHeight,
int? resizePercent,
@Default(80) int quality,
}) = _UploadMediaRequest;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const UploadMediaRequest({
required final String path,
required final bool encrypt,
final String? filename,
@JsonKey(name: "voice_message") final bool isVoiceMessage = false,
final bool forceFile = false,
final
// Below params only work if encodeTo is set
String?
encodeTo,
final int? resizeWidth,
final int? resizeHeight,
final int? resizePercent,
final int quality = 80,
}) with _$UploadMediaRequest {
Map<String, Object?> toJson() => _$UploadMediaRequestToJson(this);
factory UploadMediaRequest.fromJson(Map<String, Object?> 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/read_receipt.dart";
import "package:nexus/models/room_metadata.dart";
part "room.freezed.dart";
part "room.g.dart";
@freezed
abstract class Room with _$Room {
@Freezed(toJson: false, fromJson: false)
@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) =>
IMap.fromEntries(
json.map(
@ -26,32 +53,7 @@ abstract class Room with _$Room {
}),
);
/// [timeline] is an IMap of timelineRowId to eventRowId
/// [events] is an IMap of eventRowId to event
/// [sticky] is an ISet of eventRowId
const factory Room({
@JsonKey(name: "meta") RoomMetadata? metadata,
@Default(IMap.empty())
@JsonKey(fromJson: Room.timelineTupleJsonToIMap)
IMap<int, int?> timeline,
@Default(ISet.empty()) ISet<int> sticky,
@Default(IMap.empty())
@JsonKey(fromJson: Room.eventsJsonToIMap)
IMap<int, Event> events,
@Default(false) bool reset,
@Default(false) bool hasFetchedState,
@Default(false) bool hasFetchedMembers,
@Default(IMap.empty()) IMap<String, IMap<String, int>> state,
@Default(IMap.empty()) IMap<String, IList<ReadReceipt>> receipts,
@Default(false) bool dismissNotifications,
@Default(true) bool hasMore,
// required IMap<String, AccountData> accountData,
// required IList<Notification> notifications,
}) = _Room;
Map<String, Object?> toJson() => _$RoomToJson(this);
factory Room.fromJson(Map<String, Object?> json) => _$RoomFromJson(json);
}

View file

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

View file

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

View file

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

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