Compare commits
39
.github/workflows/android.yml
vendored
|
|
@ -1,39 +0,0 @@
|
|||
name: "Build APK"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["*"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-apk:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Lix GHA Installer Action
|
||||
uses: samueldr/lix-gha-installer-action@v2026-02-22
|
||||
with:
|
||||
extra_nix_config: experimental-features = nix-command flakes flake-self-attrs
|
||||
|
||||
- name: Decode keystore
|
||||
run: echo "$KEYSTORE_CONTENT" | base64 --decode > keystore.jks
|
||||
env:
|
||||
KEYSTORE_CONTENT: ${{ secrets.KEYSTORE_CONTENT }}
|
||||
|
||||
- name: Build app
|
||||
run: nix develop --command bash -c "flutter pub get && dart scripts/generate.dart && flutter pub run build_runner build && flutter build apk --release"
|
||||
env:
|
||||
KEYSTORE_PATH: ../../keystore.jks
|
||||
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
|
||||
|
||||
- name: Upload installer artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: APK
|
||||
path: build/app/outputs/flutter-apk/app-release.apk
|
||||
37
.github/workflows/flatpak.yml
vendored
|
|
@ -1,37 +0,0 @@
|
|||
name: "Build Flatpaks"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["*"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-flatpak:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86_64
|
||||
runner: ubuntu-latest
|
||||
- arch: aarch64
|
||||
runner: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.runner }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Lix GHA Installer Action
|
||||
uses: samueldr/lix-gha-installer-action@v2026-02-22
|
||||
with:
|
||||
extra_nix_config: experimental-features = nix-command flakes flake-self-attrs
|
||||
|
||||
- name: Build app
|
||||
run: nix build .#flatpak
|
||||
|
||||
- name: Upload installer artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: flatpak-${{ matrix.arch }}
|
||||
path: result/nexus.federated.nexus.flatpak
|
||||
48
.github/workflows/ios.yml
vendored
|
|
@ -1,48 +0,0 @@
|
|||
name: "Build iOS App"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["*"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-app:
|
||||
runs-on: macos-latest
|
||||
|
||||
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 Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: gomuks/go.mod
|
||||
|
||||
- name: Build app
|
||||
run: |
|
||||
flutter pub get
|
||||
dart scripts/generate.dart
|
||||
flutter pub run build_runner build
|
||||
flutter build ios --release --no-codesign
|
||||
|
||||
# Unsigned IPA: SideStore/AltStore re-sign this on-device with the
|
||||
# user's own Apple ID at install time, so no certificate is needed here.
|
||||
- name: Package unsigned IPA
|
||||
run: |
|
||||
mkdir Payload
|
||||
cp -r build/ios/iphoneos/Runner.app Payload/
|
||||
zip -r Nexus.ipa Payload
|
||||
|
||||
- name: Upload IPA artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: Nexus.ipa
|
||||
path: Nexus.ipa
|
||||
47
.github/workflows/macos.yml
vendored
|
|
@ -1,47 +0,0 @@
|
|||
name: "Build MacOS App"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["*"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-app:
|
||||
runs-on: macos-latest
|
||||
|
||||
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 Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: gomuks/go.mod
|
||||
|
||||
- name: Build App
|
||||
run: |
|
||||
flutter pub get
|
||||
dart scripts/generate.dart
|
||||
flutter pub run build_runner build
|
||||
flutter build macos --release
|
||||
|
||||
- name: Create DMG
|
||||
id: create-dmg
|
||||
uses: L-Super/create-dmg-actions@28511e988b13ca34096d439159a66d468b8e724f
|
||||
with:
|
||||
dmg_name: nexus
|
||||
src_dir: build/macos/Build/Products/Release/Nexus.app
|
||||
|
||||
- name: Upload DMG
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: nexus.dmg
|
||||
path: ${{ steps.create-dmg.outputs.dmg_path }}
|
||||
69
.github/workflows/windows.yml
vendored
|
|
@ -1,65 +1,46 @@
|
|||
name: "Build EXE"
|
||||
name: "Build Windows Version"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["*"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-exe:
|
||||
runs-on: windows-latest
|
||||
build-windows:
|
||||
runs-on: "windows-latest"
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: "Checkout repository"
|
||||
uses: "actions/checkout@v4"
|
||||
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version: 3.44.4
|
||||
- name: "Set up Flutter"
|
||||
uses: "subosito/flutter-action@v2"
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
- name: "Set up Rust"
|
||||
uses: "dtolnay/rust-toolchain@stable"
|
||||
with:
|
||||
go-version-file: gomuks/go.mod
|
||||
targets: "x86_64-pc-windows-msvc"
|
||||
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
install: >-
|
||||
mingw-w64-x86_64-gcc
|
||||
- name: "Install Flutter dependencies"
|
||||
run: flutter pub get
|
||||
|
||||
- name: Go build
|
||||
- name: "Run build_runner & build Windows EXE"
|
||||
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 pub run build_runner build --delete-conflicting-outputs
|
||||
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: "Upload exe zip"
|
||||
uses: "actions/upload-artifact@v4"
|
||||
with:
|
||||
name: "windows-portable"
|
||||
path: "build/windows/x64/runner/Release/"
|
||||
|
||||
- name: Install Inno Setup
|
||||
- name: "Install Inno Setup"
|
||||
run: choco install innosetup -y
|
||||
|
||||
- name: Build Inno Setup installer
|
||||
- name: "Build Inno Setup installer"
|
||||
run: iscc windows/installer.iss
|
||||
|
||||
- name: Upload installer artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
- name: "Upload installer artifact"
|
||||
uses: "actions/upload-artifact@v4"
|
||||
with:
|
||||
name: windows-installer
|
||||
path: windows/dist/Nexus-Setup.exe
|
||||
name: "windows-installer"
|
||||
path: "windows/dist/Nexus-Setup.exe"
|
||||
|
|
|
|||
6
.gitignore
vendored
|
|
@ -36,9 +36,7 @@ key.properties
|
|||
# Generated Files
|
||||
*.g.dart
|
||||
*.freezed.dart
|
||||
src/
|
||||
|
||||
# Devel Password
|
||||
password.txt
|
||||
|
||||
# Nix
|
||||
/result
|
||||
password.txt
|
||||
4
.gitmodules
vendored
|
|
@ -1,4 +0,0 @@
|
|||
[submodule "gomuks"]
|
||||
path = gomuks
|
||||
url = https://github.com/gomuks/gomuks
|
||||
branch = main
|
||||
12
.metadata
|
|
@ -4,7 +4,7 @@
|
|||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "6b182d2c7585eba26d4edce0f97630effd256c33"
|
||||
revision: "nixpkgs000000000000000000000000000000000"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
|
|
@ -13,11 +13,11 @@ project_type: app
|
|||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 6b182d2c7585eba26d4edce0f97630effd256c33
|
||||
base_revision: 6b182d2c7585eba26d4edce0f97630effd256c33
|
||||
- platform: ios
|
||||
create_revision: 6b182d2c7585eba26d4edce0f97630effd256c33
|
||||
base_revision: 6b182d2c7585eba26d4edce0f97630effd256c33
|
||||
create_revision: nixpkgs000000000000000000000000000000000
|
||||
base_revision: nixpkgs000000000000000000000000000000000
|
||||
- platform: windows
|
||||
create_revision: nixpkgs000000000000000000000000000000000
|
||||
base_revision: nixpkgs000000000000000000000000000000000
|
||||
|
||||
# User provided section
|
||||
|
||||
|
|
|
|||
9
.vscode/settings.json
vendored
|
|
@ -2,15 +2,8 @@
|
|||
"cSpell.words": [
|
||||
"Appbar",
|
||||
"Displayname",
|
||||
"fluttertagger",
|
||||
"Gomuks",
|
||||
"Homeserver",
|
||||
"Linkified",
|
||||
"localpart",
|
||||
"msgtype",
|
||||
"muks",
|
||||
"prefs",
|
||||
"unban",
|
||||
"unredact"
|
||||
"vodozemac"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
# Development Documentation
|
||||
|
||||
## Build instructions
|
||||
|
||||
Build instructions can be found in [README.md](./README.md#build-it-yourself).
|
||||
|
||||
## Updating Gomuks
|
||||
|
||||
You can run the following command to update the Gomuks submodule:
|
||||
|
||||
```sh
|
||||
git submodule update --remote
|
||||
```
|
||||
|
||||
## Code Style
|
||||
|
||||
See [Effective Dart: Style](https://dart.dev/effective-dart/style) for general rules. There are some extra rules detailed below:
|
||||
|
||||
### Controllers and Helpers ([Riverpod](https://pub.dev/packages/riverpod))
|
||||
|
||||
Controllers live in `lib/controllers/` and provide a source that exposes data and logic via Riverpod providers, allowing other parts of the code to watch state changes with ref.watch (`ref.watch(MyController.provider)`), access the current value with ref.read (`ref.read(MyController.provider)`), and run helper methods on those classes using the notifier:
|
||||
|
||||
```dart
|
||||
ref.watch(MyController.provider.notifier).helperMethod()
|
||||
```
|
||||
|
||||
We use an object oriented style for controllers, where `provider` is a static member on the controller class. E.g.
|
||||
|
||||
```dart
|
||||
class MyController extends AsyncNotifier<DataThisControllerExposes> {
|
||||
final SomeInputType input;
|
||||
MyController(this.input);
|
||||
|
||||
@override
|
||||
Future<DataThisControllerExposes> build() async {
|
||||
return input.foo;
|
||||
}
|
||||
|
||||
static final provider =
|
||||
AsyncNotifierProvider.family<MyController, DataThisControllerExposes, SomeInputType>(
|
||||
AuthorController.new,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Providers which are not controllers, e.g. they expose no data, only methods, should instead live in `lib/helpers/`. For an example, see `lib/helpers/launch_helper.dart`. Other, non-provider helpers, like extensions or helper methods can also go in `lib/helpers/`.
|
||||
|
||||
### Don't use StatefulWidgets ([Flutter Hooks](https://pub.dev/packages/flutter_hooks))
|
||||
|
||||
This project uses Flutter Hooks to help with boilerplate that StatefulWidgets create. Instead of using a StatefulWidget, we just use hooks like `useState` or `useEffect` in the build method of a `HookWidget`, which is a drop in replacement for `StatelessWidget`. If you need both a `WidgetRef` to watch providers, and access to hooks, use `HookConsumerWidget`.
|
||||
|
||||
### Models ([Freezed](https://pub.dev/packages/freezed))
|
||||
|
||||
We use Freezed for our models to avoid boilerplate and enforce an immutable style of state and data modeling throughout the code. See their documentation for more info, or see our existing models in `lib/models/`.
|
||||
|
||||
### Immutable Data Collections ([Fast Immutable Collections](https://pub.dev/packages/fast_immutable_collections))
|
||||
|
||||
When possible, use immutable collections instead of the mutable equivalent. For example, use `IMap` over `Map`, `IList` over `List`, `ISet` over `Set`. This matches the immutable style of Riverpod and Freezed.
|
||||
|
||||
### Don't create globals
|
||||
|
||||
When possible, we prefer not to create global variables or methods. You can usually replace a global variable with a Riverpod controller, and a global method with an extension method.
|
||||
|
||||
## LLM/AI Assisted Contributions
|
||||
|
||||
LLM generated code is NOT allowed. All contributions should be written by humans. Using LLMs for interacting with others, e.g. for Comments, PRs, etc, is also not allowed.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
All contributions must follow the [Federated Nexus Code of Conduct](https://federated.nexus/code/).
|
||||
292
README.md
|
|
@ -1,11 +1,11 @@
|
|||
# Nexus Client
|
||||
|
||||
> [!WARNING]
|
||||
> Nexus Client is still in development, and doesn't support everything needed for daily use.
|
||||
> Nexus Client is still heavily in development, and is not ready for use!
|
||||
|
||||
## Description
|
||||
|
||||
A simple and user-friendly Matrix client made with Flutter and a Gomuks backend.
|
||||
A simple and user-friendly Matrix client made with Flutter and the Matrix Dart SDK.
|
||||
|
||||
## Screenshots
|
||||
|
||||
|
|
@ -15,159 +15,135 @@ A simple and user-friendly Matrix client made with Flutter and a Gomuks backend.
|
|||
|
||||
## Progress
|
||||
|
||||
- [x] Platform Support
|
||||
- [x] Linux
|
||||
- [x] Windows - Currently has some bugs, due to us not having any developers on Windows. If you want to fix these, get in contact with us though the [Nexus Client Matrix room](https://matrix.to/#/#nexus:federated.nexus).
|
||||
- [x] Android
|
||||
- [x] MacOS - Unsigned .dmg only
|
||||
- [x] iOS - Unsigned .ipa only
|
||||
- [ ] Web (may not be possible)
|
||||
- [x] Login (via OAuth)
|
||||
- [x] Rooms / Spaces
|
||||
- [x] Displaying and choosing
|
||||
- [x] Reading, showing unread
|
||||
- [x] Mark as read button on rooms and spaces
|
||||
- [ ] Searching
|
||||
- [ ] Creating (Rooms, Spaces, and DMs)
|
||||
- [x] Joining
|
||||
- [x] Parse vias
|
||||
- [x] Using a text/uri/link
|
||||
- [x] Plain text
|
||||
- [x] `matrix:` Uri
|
||||
- [x] Matrix.to link
|
||||
- [ ] From space
|
||||
- [ ] From directory
|
||||
- [x] Leaving
|
||||
- [x] Subspaces
|
||||
- [x] Messages
|
||||
- [x] Encryption
|
||||
- [x] Restoring crypto identity from a recovery passphrase/key
|
||||
- [x] Sending
|
||||
- [x] Plain text
|
||||
- [x] HTML/Markdown
|
||||
- [x] Replies
|
||||
- [x] Choose ping on/off
|
||||
- [x] Per message profiles
|
||||
- [x] Attachments
|
||||
- [ ] Commands with [MSC4391](https://github.com/matrix-org/matrix-spec-proposals/pull/4391)
|
||||
- [x] Mentions
|
||||
- [x] Users
|
||||
- [x] Rooms
|
||||
- [ ] Inline emoji picker (Putting this here since it'll be implemented the same way as mentions)
|
||||
- [ ] Custom emojis/stickers
|
||||
- [ ] GIFs using Gomuks' GIF proxies
|
||||
- [x] Receiving
|
||||
- [x] Plain text
|
||||
- [x] Per message profiles
|
||||
- [x] HTML
|
||||
- [x] URL Previews
|
||||
- [x] Replies
|
||||
- [x] Viewing
|
||||
- [ ] Jump to original message
|
||||
- [x] In loaded timeline
|
||||
- [ ] Out of loaded timeline
|
||||
- [x] Edits
|
||||
- [x] Attachments
|
||||
- [x] Unencrypted
|
||||
- [x] Encrypted
|
||||
- [x] Blurhashing
|
||||
- [ ] Downloading attachments
|
||||
- [x] Opening attachments in their own view
|
||||
- [ ] Polls
|
||||
- [x] Mentions
|
||||
- [x] Users
|
||||
- [x] Clickable
|
||||
- [x] Rooms
|
||||
- [ ] Clickable
|
||||
- [x] Matrix URIs
|
||||
- [x] Matrix.to links
|
||||
- [x] Events
|
||||
- [ ] Render more nicely
|
||||
- [ ] Clickable
|
||||
- [x] Custom emojis/stickers
|
||||
- [x] History loading
|
||||
- [x] Editing
|
||||
- [x] Deleting
|
||||
- [x] Reactions
|
||||
- [x] Pins
|
||||
- [x] Displaying
|
||||
- [x] Pinning/Unpinning
|
||||
- [ ] Threads
|
||||
- [x] Profile popouts
|
||||
- [x] Working actions
|
||||
- [x] Copy link to:
|
||||
- [x] Room
|
||||
- [x] Space
|
||||
- [x] Message
|
||||
- [ ] Reporting
|
||||
- [x] Events
|
||||
- [ ] Rooms
|
||||
- [x] Member list
|
||||
- [x] Sort by power level
|
||||
- [ ] Colors based off of power level
|
||||
- [ ] Notifications using UnifiedPush ([#35](https://git.federated.nexus/Nexus/nexus/issues/35))
|
||||
- [ ] Group calls using [MSC4195](https://github.com/matrix-org/matrix-spec-proposals/pull/4195)
|
||||
- [ ] Invites
|
||||
- [x] Settings
|
||||
- [ ] New logo
|
||||
- [ ] Make context menus appear as bottom sheets on mobile
|
||||
- [x] Move from the Dart SDK to the Gomuks SDK with Dart bindings: https://git.federated.nexus/Henry-Hiles/nexus/pulls/2
|
||||
- [ ] Allow using remote gomuks over websocket
|
||||
- [ ] Platform Support
|
||||
- [x] Linux
|
||||
- [x] Windows
|
||||
- [ ] MacOS
|
||||
- [ ] Android
|
||||
- [ ] iOS
|
||||
- [ ] Web (may not be possible)
|
||||
- [x] Login
|
||||
- [x] Username / password auth
|
||||
- [ ] OAuth / OIDC
|
||||
- [x] Improve initial sync experience
|
||||
- [x] Rooms / Spaces
|
||||
- [x] Displaying and choosing
|
||||
- [x] Reading, showing unread
|
||||
- [x] Mark as read button on rooms and spaces
|
||||
- [ ] Searching
|
||||
- [ ] Creating (Rooms, Spaces, and DMs)
|
||||
- [x] Joining
|
||||
- [ ] Parse vias
|
||||
- [x] Using a text/uri/link
|
||||
- [x] Plain text
|
||||
- [x] `matrix:` Uri
|
||||
- [x] Matrix.to link
|
||||
- [ ] From space
|
||||
- [ ] Exploring
|
||||
- [x] Leaving
|
||||
- [x] Subspaces
|
||||
- [x] Messages
|
||||
- [x] Encryption
|
||||
- [x] Restoring crypto identity from a recovery passphrase/key
|
||||
- [x] Sending
|
||||
- [x] Plain text
|
||||
- [x] HTML/Markdown
|
||||
- [x] Replies
|
||||
- [x] Choose ping on/off
|
||||
- [ ] Per message profiles
|
||||
- [ ] Attachments
|
||||
- [ ] Commands with [MSC4391](https://github.com/matrix-org/matrix-spec-proposals/pull/4391)
|
||||
- [x] Mentions
|
||||
- [x] Users
|
||||
- [x] Rooms
|
||||
- [ ] Inline emoji picker (Putting this here since it'll be implemented the same way as mentions)
|
||||
- [ ] Custom emojis/stickers
|
||||
- [ ] GIFs using Gomuks' GIF proxies
|
||||
- [x] Recieving
|
||||
- [x] Plain text
|
||||
- [x] Per message profiles
|
||||
- [x] HTML
|
||||
- [x] Replies
|
||||
- [x] Viewing
|
||||
- [ ] Jump to original message
|
||||
- [x] In loaded timeline
|
||||
- [ ] Out of loaded timeline
|
||||
- [x] Edits
|
||||
- [x] Attachments
|
||||
- [x] Unencrypted
|
||||
- [ ] Encrypted
|
||||
- [x] Blurhashing
|
||||
- [ ] Downloading attachments
|
||||
- [x] Opening attachments in their own view
|
||||
- [ ] Polls: Waiting on https://github.com/SwanFlutter/dynamic_polls/issues/1
|
||||
- [x] Mentions
|
||||
- [x] Users
|
||||
- [x] Rooms
|
||||
- [ ] Plain text (not sure if I want to add this or not, I probably won't unless there's interest)
|
||||
- [x] Matrix URIs
|
||||
- [x] Matrix.to links
|
||||
- [ ] Do some fancy fetching to get nice names
|
||||
- [ ] Make clickable
|
||||
- [x] Custom emojis/stickers
|
||||
- [x] History loading
|
||||
- [x] Backwards
|
||||
- [ ] Forwards
|
||||
- [x] Editing
|
||||
- [x] Deleting
|
||||
- [ ] Reactions: Waiting on https://github.com/flyerhq/flutter_chat_ui/pull/838 or me doing a custom impl
|
||||
- [ ] Pins
|
||||
- [ ] Displaying
|
||||
- [ ] Creating
|
||||
- [ ] Threads
|
||||
- [ ] Profile popouts
|
||||
- [ ] Copy link to [room, space]
|
||||
- [ ] Reporting
|
||||
- [x] Events
|
||||
- [ ] Rooms
|
||||
- [ ] Notifications using UnifiedPush
|
||||
- [ ] Group calls using [MSC4195](https://github.com/matrix-org/matrix-spec-proposals/pull/4195)
|
||||
- [ ] Invites
|
||||
- [ ] Settings
|
||||
- [ ] Light/Dark mode
|
||||
- [ ] SSD or CSD
|
||||
- [ ] Show media by default
|
||||
- [ ] Dynamic Theming
|
||||
- [ ] Devices
|
||||
- [ ] Viewing devices
|
||||
- [ ] Verifying devices
|
||||
- [ ] URL preview: Server / Client / None
|
||||
- [ ] Account changes
|
||||
- [ ] Display name
|
||||
- [ ] Profile picture
|
||||
- [ ] Timezone
|
||||
- [ ] Pronouns
|
||||
- [ ] Password
|
||||
- [ ] About
|
||||
- [x] Log Out
|
||||
|
||||
## Try it out
|
||||
## Build Instructions
|
||||
|
||||
If you want to try out Nexus, grab one of the following artifacts from CI:
|
||||
First, clone and open the repo:
|
||||
|
||||
- [Android APK](https://nightly.link/Henry-Hiles/nexus/workflows/android/main/APK.zip)
|
||||
- [Windows EXE](https://nightly.link/Henry-Hiles/nexus/workflows/windows/main/windows-installer.zip)
|
||||
- [Unsigned iOS IPA](https://nightly.link/Henry-Hiles/nexus/workflows/ios/main/Nexus.ipa.zip)
|
||||
- [Unsigned MacOS DMG](https://nightly.link/Henry-Hiles/nexus/workflows/macos/main/nexus.dmg.zip)
|
||||
- [Windows EXE](https://nightly.link/Henry-Hiles/nexus/workflows/windows/main/windows-installer.zip)
|
||||
- Flatpak
|
||||
- [AArch64/Arm64](https://nightly.link/Henry-Hiles/nexus/workflows/flatpak/main/flatpak-aarch64.zip)
|
||||
- [x86_64/AMD64](https://nightly.link/Henry-Hiles/nexus/workflows/flatpak/main/flatpak-x86_64.zip)
|
||||
|
||||
## Build it yourself
|
||||
```sh
|
||||
git clone https://git.federated.nexus/Henry-Hiles/nexus
|
||||
cd nexus
|
||||
```
|
||||
|
||||
### Prerequisites
|
||||
|
||||
#### Linux
|
||||
|
||||
- On NixOS: Either use direnv and `direnv allow`, or `nix flake develop`
|
||||
- On other distros: Install Flutter, Go, Git, Libclang, Libass, MPV, and Glibc. Do not use any Snap packages, they cause various compilation issues.
|
||||
- With Nix: Either use direnv, or `nix flake develop`
|
||||
- Without Nix: Install Flutter, Go, Olm, Git, Clang, and GLibc.
|
||||
|
||||
#### Windows
|
||||
#### Windows / MacOS
|
||||
|
||||
You will need:
|
||||
|
||||
- Flutter
|
||||
- Git
|
||||
- Libass
|
||||
- MPV
|
||||
- Go
|
||||
- Visual Studio 2022 (Desktop development with C++)
|
||||
- [MSYS2/MinGW-w64 GCC](https://www.msys2.org/) (for CGO)
|
||||
- [LLVM/Clang + libclang](https://clang.llvm.org/get_started.html) (for `ffigen`)
|
||||
|
||||
On Windows, make sure these are available in your shell `PATH`:
|
||||
|
||||
- `C:\msys64\ucrt64\bin` (or your MinGW bin path containing `x86_64-w64-mingw32-gcc.exe`)
|
||||
- `C:\Program Files\LLVM\bin` (contains `clang.exe` and `libclang.dll`)
|
||||
|
||||
For `dart scripts/generate.dart`, you may also need:
|
||||
|
||||
```powershell
|
||||
$env:CPATH = "C:\msys64\ucrt64\include"
|
||||
```
|
||||
|
||||
#### MacOS
|
||||
|
||||
Similar prerequisites apply (Flutter, Git, Go, C toolchain, LLVM/libclang), but exact setup has not been fully documented yet.
|
||||
|
||||
### Clone repo
|
||||
|
||||
First, clone and open the repo:
|
||||
|
||||
```sh
|
||||
git clone --recurse-submodules https://git.federated.nexus/Nexus/nexus
|
||||
cd nexus
|
||||
```
|
||||
I don't really know. You will need Flutter, Git, Olm, Go, and Visual Studio tools, and otherwise I guess just keep installing stuff until there aren't any errors. I will look into this sometimeTM.
|
||||
|
||||
### Set up Flutter
|
||||
|
||||
|
|
@ -177,23 +153,22 @@ Get dependencies:
|
|||
flutter pub get
|
||||
```
|
||||
|
||||
Generate Gomuks bindings:
|
||||
Get dependencies:
|
||||
|
||||
```sh
|
||||
dart scripts/generate.dart
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If you are having issues with `stddef.h` not being found, try setting CPATH manually:
|
||||
>
|
||||
> ```sh
|
||||
> export CPATH="$(clang -v 2>&1 | grep "Selected GCC installation" | rev | cut -d' ' -f1 | rev)/include"
|
||||
> ```
|
||||
Clone Gomuks and generate bindings:
|
||||
|
||||
```sh
|
||||
scripts/generate.sh
|
||||
```
|
||||
|
||||
Build generated files, and watch for new changes:
|
||||
|
||||
```sh
|
||||
flutter pub run build_runner watch
|
||||
flutter pub run build_runner watch --delete-conflicting-outputs
|
||||
```
|
||||
|
||||
Run the app:
|
||||
|
|
@ -202,13 +177,6 @@ Run the app:
|
|||
flutter run
|
||||
```
|
||||
|
||||
Development instructions can be found in [DEVELOPMENT.md](./DEVELOPMENT.md).
|
||||
|
||||
## Community
|
||||
|
||||
Join the [Nexus Client Matrix room](https://matrix.to/#/#nexus:federated.nexus) for questions or help with developing or using Nexus Client.
|
||||
|
||||
# Credits
|
||||
|
||||
Thank you Hylke Bons (https://planetpeanut.studio) for making the amazing icon for Nexus!
|
||||
Thank you Tulir Asokan for making [Gomuks](https://github.com/gomuks/gomuks), and helping us integrate it into Nexus!
|
||||
Join the [Nexus Client Matrix Room](https://matrix.to/#/#nexus:federated.nexus) for questions or help with developing or using Nexus Client.
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"name": "Nexus",
|
||||
"identifier": "nexus.federated.nexus.source",
|
||||
"subtitle": "Nexus for iOS",
|
||||
"description": "Nexus iOS builds for AltStore and SideStore.",
|
||||
"iconURL": "https://git.federated.nexus/Nexus/nexus/raw/branch/main/assets/icon.png",
|
||||
"website": "https://git.federated.nexus/Nexus/nexus",
|
||||
"apps": [
|
||||
{
|
||||
"name": "Nexus",
|
||||
"bundleIdentifier": "nexus.federated.nexus",
|
||||
"developerName": "Nexus",
|
||||
"subtitle": "A Matrix client",
|
||||
"localizedDescription": "Nexus for iOS. Unsigned builds, resigned at install by AltStore/SideStore.",
|
||||
"iconURL": "https://git.federated.nexus/Nexus/nexus/raw/branch/main/assets/icon.png",
|
||||
"category": "social",
|
||||
"screenshots": [],
|
||||
"versions": []
|
||||
}
|
||||
],
|
||||
"news": []
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ if (keystorePropertiesFile.exists()) {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace = "nexus.federated.nexus"
|
||||
namespace = "nexus.federated.Nexus"
|
||||
ndkVersion = flutter.ndkVersion
|
||||
compileSdk = 34
|
||||
|
||||
|
|
@ -39,12 +39,8 @@ android {
|
|||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "nexus.federated.nexus"
|
||||
applicationId = "nexus.federated.Nexus"
|
||||
minSdk = 29
|
||||
targetSdkVersion flutter.targetSdkVersion
|
||||
versionCode = flutterVersionCode.toInteger()
|
||||
|
|
@ -54,8 +50,7 @@ android {
|
|||
signingConfigs {
|
||||
release {
|
||||
keyAlias "key"
|
||||
def storePath = keystoreProperties['path'] ?: System.getenv("KEYSTORE_PATH")
|
||||
storeFile storePath ? file(storePath) : null
|
||||
storeFile keystoreProperties['path'] ? file(keystoreProperties['path']) : file(System.getenv("KEYSTORE_PATH"))
|
||||
keyPassword keystoreProperties['password'] ?: System.getenv("KEYSTORE_PASSWORD")
|
||||
storePassword keystoreProperties['password'] ?: System.getenv("KEYSTORE_PASSWORD")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
android:label="Nexus"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/nexus_round"
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false">
|
||||
<activity
|
||||
|
|
@ -22,14 +22,6 @@
|
|||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<meta-data android:name="flutter_deeplinking_enabled" android:value="false" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="nexus.federated.nexus" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package nexus.federated.nexus
|
||||
package nexus.federated.Nexus
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 8.2 KiB |
|
|
@ -1,14 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_launcher_foreground"
|
||||
android:inset="16%" />
|
||||
</foreground>
|
||||
<monochrome>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_launcher_monochrome"
|
||||
android:inset="16%" />
|
||||
</monochrome>
|
||||
</adaptive-icon>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 19 KiB |
|
|
@ -1,7 +1,3 @@
|
|||
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
# This builtInKotlin flag was added automatically by Flutter migrator
|
||||
android.builtInKotlin=false
|
||||
# This newDsl flag was added automatically by Flutter migrator
|
||||
android.newDsl=false
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 21 KiB |
|
|
@ -1,257 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg11"
|
||||
sodipodi:docname="background.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
inkscape:export-filename="background.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="0.69191503"
|
||||
inkscape:cx="-71.540576"
|
||||
inkscape:cy="281.10388"
|
||||
inkscape:window-width="2544"
|
||||
inkscape:window-height="1363"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg11" />
|
||||
<defs
|
||||
id="defs11">
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(3.5,24.5214,-15.8099,2.26053,80,52.9904)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11" />
|
||||
</radialGradient>
|
||||
<mask
|
||||
id="mask0_4033_8"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="56"
|
||||
y="46"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 76.4223,63.1501 c 0.3482,0.5123 0.3457,1.1859 -0.0063,1.6956 L 65.0175,81.3524 C 64.7375,81.7579 64.2761,82 63.7832,82 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.332 l 9.8906,-14.8359 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6641 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6568 z"
|
||||
fill="#2779dd"
|
||||
id="path9" />
|
||||
</mask>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath11">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect12"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath12">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect13"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath13">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect14"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath14">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect15"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath15">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect16"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath16">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect17"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8-3"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(3.5,24.5214,-15.8099,2.26053,174.26633,65.9904)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10-6" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11-7" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8-35"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(3.5,24.5214,-15.8099,2.26053,80,52.9904)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10-62" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11-9" />
|
||||
</radialGradient>
|
||||
<mask
|
||||
id="mask0_4033_8-1"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="56"
|
||||
y="46"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 76.4223,63.1501 c 0.3482,0.5123 0.3457,1.1859 -0.0063,1.6956 L 65.0175,81.3524 C 64.7375,81.7579 64.2761,82 63.7832,82 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.332 l 9.8906,-14.8359 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6641 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6568 z"
|
||||
fill="#2779dd"
|
||||
id="path9-2" />
|
||||
</mask>
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8-9"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(14,98.0856,-63.2396,9.04212,320,211.9616)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10-3" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11-6" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<rect
|
||||
width="512"
|
||||
height="512"
|
||||
fill="#ffffff"
|
||||
id="rect1"
|
||||
x="0"
|
||||
y="0"
|
||||
style="stroke-width:4" />
|
||||
<rect
|
||||
x="-1.5384758"
|
||||
y="-122.66472"
|
||||
width="35.5569"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#9141ac"
|
||||
id="rect2"
|
||||
clip-path="url(#clipPath16)" />
|
||||
<rect
|
||||
x="34.018467"
|
||||
y="-122.66468"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#62a0ea"
|
||||
id="rect3"
|
||||
clip-path="url(#clipPath15)" />
|
||||
<rect
|
||||
x="60.68605"
|
||||
y="-122.66468"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#57e389"
|
||||
id="rect4"
|
||||
clip-path="url(#clipPath14)" />
|
||||
<rect
|
||||
x="87.353859"
|
||||
y="-122.66468"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#f5c211"
|
||||
id="rect5"
|
||||
clip-path="url(#clipPath13)" />
|
||||
<rect
|
||||
x="114.02161"
|
||||
y="-122.66477"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#ff7800"
|
||||
id="rect6"
|
||||
clip-path="url(#clipPath12)" />
|
||||
<rect
|
||||
x="140.68942"
|
||||
y="-122.66477"
|
||||
width="35.5569"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#ed333b"
|
||||
id="rect7"
|
||||
clip-path="url(#clipPath11)" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 20 KiB |
|
|
@ -1,19 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
fill="none"
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
id="svg11"
|
||||
sodipodi:docname="foreground.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="nexus.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
|
|
@ -21,137 +22,105 @@
|
|||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="0.87695313"
|
||||
inkscape:cx="152.23163"
|
||||
inkscape:cy="347.22494"
|
||||
inkscape:window-width="2544"
|
||||
inkscape:window-height="1363"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="1.0847363"
|
||||
inkscape:cx="58.07863"
|
||||
inkscape:cy="214.3378"
|
||||
inkscape:window-width="1896"
|
||||
inkscape:window-height="987"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg11" />
|
||||
<path
|
||||
d="m 256,92 c 90.5748,0 164,73.4252 164,164 0,90.5748 -73.4252,164 -164,164 -34.5828,0 -66.6592,-10.712 -93.1092,-28.9884 l -39.2072,8.7656 c -6.8668,1.5348 -12.9952,-4.594 -11.4608,-11.4608 l 8.7616,-39.2108 C 102.7104,322.6564 92,290.5808 92,256 92,165.4252 165.4252,92 256,92 Z"
|
||||
fill="#ffffff"
|
||||
id="path7"
|
||||
style="stroke-width:4" />
|
||||
<path
|
||||
d="m 304.9188,251.4672 c 1.8572,2.732 1.844,6.3248 -0.0332,9.0432 L 260.6664,324.546 C 259.1728,326.7088 256.712,328 254.0836,328 H 234.948 c -6.3896,0 -10.2004,-7.1212 -6.6564,-12.4376 l 36.75,-55.1248 c 1.7916,-2.6872 1.7916,-6.188 0,-8.8752 l -36.75,-55.1248 C 224.7476,191.1212 228.5584,184 234.948,184 h 19.8748 c 2.6492,0 5.1268,1.3116 6.616,3.5028 z"
|
||||
fill="url(#paint0_radial_4033_8)"
|
||||
id="path8"
|
||||
style="fill:url(#paint0_radial_4033_8);stroke-width:4" />
|
||||
<g
|
||||
mask="url(#mask0_4033_8)"
|
||||
id="g9"
|
||||
transform="scale(4)">
|
||||
<rect
|
||||
x="52"
|
||||
y="46"
|
||||
width="17"
|
||||
height="4"
|
||||
fill="#2779dd"
|
||||
id="rect9" />
|
||||
</g>
|
||||
<defs
|
||||
id="defs11">
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(14,98.0856,-63.2396,9.04212,320,211.9616)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11" />
|
||||
</radialGradient>
|
||||
<mask
|
||||
id="mask0_4033_8"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="56"
|
||||
y="46"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 76.4223,63.1501 c 0.3482,0.5123 0.3457,1.1859 -0.0063,1.6956 L 65.0175,81.3524 C 64.7375,81.7579 64.2761,82 63.7832,82 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.332 l 9.8906,-14.8359 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6641 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6568 z"
|
||||
fill="#2779dd"
|
||||
id="path9" />
|
||||
</mask>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath11">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect12"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath12">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect13"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath13">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect14"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath14">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect15"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath15">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect16"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath16">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect17"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
inkscape:current-layer="layer1" /><defs
|
||||
id="defs1" /><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="M 19.377906,68.106953 80.937684,32.43771"
|
||||
id="path10" /><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="m 19.044488,32.469148 61.61782,35.569625"
|
||||
id="path9" /><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="M 50,85.574911 V 14.425087"
|
||||
id="path8" /><circle
|
||||
style="fill:none;stroke:#ffffff;stroke-width:7.11498;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="path1"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="35.574913" /><circle
|
||||
style="fill:#09bd05;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="path2"
|
||||
cx="50"
|
||||
cy="84.604881"
|
||||
r="8.2508707" /><circle
|
||||
style="fill:#fe1e24;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle2"
|
||||
cx="50"
|
||||
cy="15.395123"
|
||||
r="8.2508707" /><circle
|
||||
style="fill:#fe941d;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle3"
|
||||
cx="-68.30127"
|
||||
cy="52.906147"
|
||||
r="8.2508707"
|
||||
transform="rotate(-120)" /><circle
|
||||
style="fill:#001996;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle4"
|
||||
cx="-68.30127"
|
||||
cy="-16.30361"
|
||||
r="8.2508707"
|
||||
transform="rotate(-120)" /><circle
|
||||
style="fill:#ffff04;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle5"
|
||||
cx="-18.301271"
|
||||
cy="102.90615"
|
||||
r="8.2508707"
|
||||
transform="rotate(-60)" /><circle
|
||||
style="fill:#770287;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle6"
|
||||
cx="-18.301271"
|
||||
cy="33.696392"
|
||||
r="8.2508707"
|
||||
transform="rotate(-60)" /><circle
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:6.75;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path7"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="9.7918472" /><g
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1-3"
|
||||
transform="matrix(0.08246781,0,0,0.08246781,38.828362,38.828362)"
|
||||
style="stroke:#ffffff"><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:96.3615px;line-height:0;font-family:'Noto Serif';-inkscape-font-specification:'Noto Serif, Heavy';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="-305.64749"
|
||||
y="194.14493"
|
||||
id="text2819"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2817"
|
||||
style="stroke:#ffffff;stroke-width:0"
|
||||
x="-305.64749"
|
||||
y="194.14493" /></text><circle
|
||||
style="fill:#354b5f;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path342"
|
||||
cx="135.46666"
|
||||
cy="135.46666"
|
||||
r="135.46666" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:96.3615px;line-height:0;font-family:'Noto Serif';-inkscape-font-specification:'Noto Serif, Heavy';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="-305.64749"
|
||||
y="194.14493"
|
||||
id="text2819-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2817-5"
|
||||
style="stroke:#ffffff;stroke-width:0"
|
||||
x="-305.64749"
|
||||
y="194.14493" /></text><g
|
||||
aria-label="❯"
|
||||
id="text2827-6"
|
||||
style="font-size:132.452px;line-height:0;font-family:PowerlineSymbols;-inkscape-font-specification:'PowerlineSymbols, Normal';text-align:end;text-anchor:end;fill:#4e94e4;fill-opacity:1;stroke:#ffffff;stroke-width:0"><path
|
||||
d="M 95.096912,209.8167 143.88912,135.46666 95.096912,61.116629 h 32.818568 l 47.92093,74.350031 -47.92093,74.35004 z"
|
||||
id="path2883-2"
|
||||
style="fill:#4e94e4;fill-opacity:1;stroke:#ffffff;stroke-width:0" /></g></g></g></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 6 KiB |
BIN
assets/icon.png
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 35 KiB |
448
assets/icon.svg
|
|
@ -1,22 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
fill="none"
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
id="svg35"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
inkscape:export-filename="icon.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview35"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
|
|
@ -24,311 +23,128 @@
|
|||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="1.321682"
|
||||
inkscape:cx="69.608271"
|
||||
inkscape:cy="120.67956"
|
||||
inkscape:window-width="2544"
|
||||
inkscape:window-height="1363"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="1.0847363"
|
||||
inkscape:cx="57.61769"
|
||||
inkscape:cy="214.33781"
|
||||
inkscape:window-width="1896"
|
||||
inkscape:window-height="963"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg35" />
|
||||
<mask
|
||||
id="mask0_4023_558"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="12"
|
||||
y="100"
|
||||
width="88"
|
||||
height="16">
|
||||
<path
|
||||
d="m 100,104 c 0,6.627 -5.3726,12 -12,12 H 24 c -6.6274,0 -12,-5.373 -12,-12 v -4 c 0,6.627 5.3726,12 12,12 h 64 c 6.6274,0 12,-5.373 12,-12 z"
|
||||
fill="#d9d9d9"
|
||||
id="path6" />
|
||||
</mask>
|
||||
<mask
|
||||
id="mask1_4023_558"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="77"
|
||||
y="27"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 97.4223,44.1501 c 0.3482,0.5122 0.3457,1.1859 -0.0063,1.6956 L 86.0175,62.3523 C 85.7375,62.7579 85.2761,63 84.7832,63 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.3321 l 9.8906,-14.8358 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6642 L 78.0729,30.1094 C 77.1869,28.7803 78.1396,27 79.737,27 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6567 z"
|
||||
fill="#2779dd"
|
||||
id="path14" />
|
||||
</mask>
|
||||
<g
|
||||
id="g36"
|
||||
transform="scale(4)">
|
||||
<g
|
||||
clip-path="url(#clip0_4023_558)"
|
||||
id="g6">
|
||||
<rect
|
||||
x="62.0205"
|
||||
y="-52.425598"
|
||||
width="24"
|
||||
height="197"
|
||||
transform="rotate(30,62.0205,-52.4256)"
|
||||
fill="#9141ac"
|
||||
id="rect1" />
|
||||
<rect
|
||||
x="82.805099"
|
||||
y="-40.425598"
|
||||
width="18"
|
||||
height="197"
|
||||
transform="rotate(30,82.8051,-40.4256)"
|
||||
fill="#62a0ea"
|
||||
id="rect2" />
|
||||
<rect
|
||||
x="98.3936"
|
||||
y="-31.4256"
|
||||
width="18"
|
||||
height="197"
|
||||
transform="rotate(30,98.3936,-31.4256)"
|
||||
fill="#57e389"
|
||||
id="rect3" />
|
||||
<rect
|
||||
x="113.982"
|
||||
y="-22.4256"
|
||||
width="18"
|
||||
height="197"
|
||||
transform="rotate(30,113.982,-22.4256)"
|
||||
fill="#f5c211"
|
||||
id="rect4" />
|
||||
<rect
|
||||
x="129.57001"
|
||||
y="-13.4256"
|
||||
width="18"
|
||||
height="197"
|
||||
transform="rotate(30,129.57,-13.4256)"
|
||||
fill="#ff7800"
|
||||
id="rect5" />
|
||||
<rect
|
||||
x="145.159"
|
||||
y="-4.4256301"
|
||||
width="24"
|
||||
height="197"
|
||||
transform="rotate(30,145.159,-4.42563)"
|
||||
fill="#ed333b"
|
||||
id="rect6" />
|
||||
</g>
|
||||
<g
|
||||
mask="url(#mask0_4023_558)"
|
||||
id="g10">
|
||||
<path
|
||||
d="m 12,100 h 24 v 16 H 12 Z"
|
||||
fill="url(#paint0_linear_4023_558)"
|
||||
id="path7"
|
||||
style="fill:url(#paint0_linear_4023_558)" />
|
||||
<path
|
||||
d="m 12,100 h 5 v 16 h -5 z"
|
||||
fill="url(#paint1_linear_4023_558)"
|
||||
id="path8"
|
||||
style="fill:url(#paint1_linear_4023_558)" />
|
||||
<rect
|
||||
x="36"
|
||||
y="100"
|
||||
width="21"
|
||||
height="16"
|
||||
fill="#ca9005"
|
||||
id="rect8" />
|
||||
<rect
|
||||
x="57"
|
||||
y="100"
|
||||
width="21"
|
||||
height="16"
|
||||
fill="#c64600"
|
||||
id="rect9" />
|
||||
<rect
|
||||
x="78"
|
||||
y="100"
|
||||
width="22"
|
||||
height="16"
|
||||
fill="url(#paint2_linear_4023_558)"
|
||||
id="rect10"
|
||||
style="fill:url(#paint2_linear_4023_558)" />
|
||||
</g>
|
||||
<rect
|
||||
opacity="0.2"
|
||||
x="24.5"
|
||||
y="110.5"
|
||||
width="63"
|
||||
height="1"
|
||||
stroke="url(#paint3_linear_4023_558)"
|
||||
id="rect11"
|
||||
style="stroke:url(#paint3_linear_4023_558)" />
|
||||
<path
|
||||
d="m 85,4 c 22.644,0 41,18.3563 41,41 v 4 c 0,22.6437 -18.356,41 -41,41 -8.3322,0 -16.0825,-2.4875 -22.5526,-6.7576 -0.4653,-0.3071 -1.0341,-0.4203 -1.5783,-0.2987 l -8.8369,1.9749 C 52.0134,84.9228 52,84.9395 52,84.9588 52,84.9816 51.9816,85 51.9588,85 h -0.4617 c -0.0787,0.0036 -0.1564,0.004 -0.2334,0 H 51 c -1.1046,0 -2,-0.8954 -2,-2 v -0.2617 c -0.0043,-0.0811 -0.0042,-0.1632 0,-0.2461 V 78.9749 C 49,78.7126 49.2126,78.5 49.4749,78.5 c 0.2224,0 0.4151,-0.1543 0.4635,-0.3714 l 1.117,-4.9987 C 51.177,72.5857 51.0638,72.017 50.7567,71.5517 46.487,65.0818 44,57.3317 44,49 V 45 C 44,22.3563 62.3563,4 85,4 Z"
|
||||
fill="url(#paint4_linear_4023_558)"
|
||||
id="path11"
|
||||
style="fill:url(#paint4_linear_4023_558)" />
|
||||
<path
|
||||
d="m 85,4 c 22.644,0 41,18.3563 41,41 0,22.6437 -18.356,41 -41,41 -8.6457,0 -16.6648,-2.6781 -23.2773,-7.2471 l -9.8018,2.1914 c -1.7167,0.3836 -3.2488,-1.1485 -2.8652,-2.8652 l 2.1904,-9.8027 C 46.6776,61.6641 44,53.6452 44,45 44,22.3563 62.3563,4 85,4 Z"
|
||||
fill="#ffffff"
|
||||
id="path12" />
|
||||
<path
|
||||
d="m 97.2297,43.8668 c 0.4642,0.683 0.4609,1.5812 -0.0083,2.2608 L 86.1666,62.1365 C 85.7932,62.6772 85.178,63 84.5209,63 H 79.737 c -1.5974,0 -2.5502,-1.7803 -1.6641,-3.1094 l 9.1875,-13.7812 c 0.4478,-0.6718 0.4478,-1.547 0,-2.2188 L 78.0729,30.1094 C 77.1868,28.7803 78.1396,27 79.737,27 h 4.9687 c 0.6623,0 1.2817,0.3279 1.654,0.8757 z"
|
||||
fill="url(#paint5_radial_4023_558)"
|
||||
id="path13"
|
||||
style="fill:url(#paint5_radial_4023_558)" />
|
||||
<g
|
||||
mask="url(#mask1_4023_558)"
|
||||
id="g14">
|
||||
<rect
|
||||
x="73"
|
||||
y="27"
|
||||
width="17"
|
||||
height="4"
|
||||
fill="#2779dd"
|
||||
id="rect14" />
|
||||
</g>
|
||||
</g>
|
||||
<defs
|
||||
id="defs35">
|
||||
<linearGradient
|
||||
id="paint0_linear_4023_558"
|
||||
x1="34"
|
||||
y1="108"
|
||||
x2="12"
|
||||
y2="108"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0.401381"
|
||||
stop-color="#26A269"
|
||||
id="stop14" />
|
||||
<stop
|
||||
offset="0.801049"
|
||||
stop-color="#8AEB52"
|
||||
id="stop15" />
|
||||
<stop
|
||||
inkscape:current-layer="layer1" /><defs
|
||||
id="defs1"><linearGradient
|
||||
id="linearGradient10"
|
||||
inkscape:collect="always"><stop
|
||||
style="stop-color:#c7a312;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop10" /><stop
|
||||
style="stop-color:#26a0b3;stop-opacity:1;"
|
||||
offset="1"
|
||||
stop-color="#26A269"
|
||||
id="stop16" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint1_linear_4023_558"
|
||||
x1="12"
|
||||
y1="108"
|
||||
x2="17"
|
||||
y2="108"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#1A5FB4"
|
||||
id="stop17" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#35E0F6"
|
||||
id="stop18" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint2_linear_4023_558"
|
||||
x1="100"
|
||||
y1="108"
|
||||
x2="78"
|
||||
y2="108"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#A51D2D"
|
||||
id="stop19" />
|
||||
<stop
|
||||
offset="0.195858"
|
||||
stop-color="#E5673C"
|
||||
id="stop20" />
|
||||
<stop
|
||||
offset="0.5983"
|
||||
stop-color="#A51D2D"
|
||||
id="stop21" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint3_linear_4023_558"
|
||||
x1="88"
|
||||
y1="111.329"
|
||||
x2="24"
|
||||
y2="111.329"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0.102371"
|
||||
stop-color="white"
|
||||
stop-opacity="0"
|
||||
id="stop22" />
|
||||
<stop
|
||||
offset="0.253808"
|
||||
stop-color="white"
|
||||
id="stop23" />
|
||||
<stop
|
||||
offset="0.747697"
|
||||
stop-color="white"
|
||||
id="stop24" />
|
||||
<stop
|
||||
offset="0.895556"
|
||||
stop-color="white"
|
||||
stop-opacity="0"
|
||||
id="stop25" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint4_linear_4023_558"
|
||||
x1="44"
|
||||
y1="48.036098"
|
||||
x2="126"
|
||||
y2="48.036098"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#DBEBF4"
|
||||
id="stop26" />
|
||||
<stop
|
||||
offset="0.147387"
|
||||
stop-color="#B1D4E7"
|
||||
id="stop27" />
|
||||
<stop
|
||||
offset="0.186621"
|
||||
stop-color="#8DC0DC"
|
||||
id="stop28" />
|
||||
<stop
|
||||
offset="0.203755"
|
||||
stop-color="#49AEE7"
|
||||
id="stop29" />
|
||||
<stop
|
||||
offset="0.276122"
|
||||
stop-color="#7AB5D7"
|
||||
id="stop30" />
|
||||
<stop
|
||||
offset="0.399628"
|
||||
stop-color="#B3D6E7"
|
||||
id="stop31" />
|
||||
<stop
|
||||
offset="0.507537"
|
||||
stop-color="#B3D6E7"
|
||||
id="stop32" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#DBEBF4"
|
||||
id="stop33" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
id="paint5_radial_4023_558"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(3.5,24.5214,-15.8099,2.26053,101,33.9904)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop34" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop35" />
|
||||
</radialGradient>
|
||||
<clipPath
|
||||
id="clip0_4023_558">
|
||||
<rect
|
||||
x="12"
|
||||
y="36"
|
||||
width="88"
|
||||
height="80"
|
||||
rx="12"
|
||||
fill="#ffffff"
|
||||
id="rect35" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
id="stop11" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient10"
|
||||
id="linearGradient11"
|
||||
x1="20.031296"
|
||||
y1="32.697563"
|
||||
x2="90.709213"
|
||||
y2="66.3423"
|
||||
gradientUnits="userSpaceOnUse" /></defs><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"><rect
|
||||
style="fill:url(#linearGradient11);fill-opacity:1;stroke:none;stroke-width:7.99999;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="rect10"
|
||||
width="100"
|
||||
height="100"
|
||||
x="0"
|
||||
y="0"
|
||||
ry="28.294127" /><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="M 19.377906,68.106953 80.937684,32.43771"
|
||||
id="path10" /><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="m 19.044488,32.469148 61.61782,35.569625"
|
||||
id="path9" /><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="M 50,85.574911 V 14.425087"
|
||||
id="path8" /><circle
|
||||
style="fill:none;stroke:#ffffff;stroke-width:7.11498;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="path1"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="35.574913" /><circle
|
||||
style="fill:#09bd05;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="path2"
|
||||
cx="50"
|
||||
cy="84.604881"
|
||||
r="8.2508707" /><circle
|
||||
style="fill:#fe1e24;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle2"
|
||||
cx="50"
|
||||
cy="15.395123"
|
||||
r="8.2508707" /><circle
|
||||
style="fill:#fe941d;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle3"
|
||||
cx="-68.30127"
|
||||
cy="52.906147"
|
||||
r="8.2508707"
|
||||
transform="rotate(-120)" /><circle
|
||||
style="fill:#001996;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle4"
|
||||
cx="-68.30127"
|
||||
cy="-16.30361"
|
||||
r="8.2508707"
|
||||
transform="rotate(-120)" /><circle
|
||||
style="fill:#ffff04;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle5"
|
||||
cx="-18.301271"
|
||||
cy="102.90615"
|
||||
r="8.2508707"
|
||||
transform="rotate(-60)" /><circle
|
||||
style="fill:#770287;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle6"
|
||||
cx="-18.301271"
|
||||
cy="33.696392"
|
||||
r="8.2508707"
|
||||
transform="rotate(-60)" /><circle
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:6.75;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path7"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="9.7918472" /><g
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1-3"
|
||||
transform="matrix(0.08246781,0,0,0.08246781,38.828362,38.828362)"
|
||||
style="stroke:#ffffff"><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:96.3615px;line-height:0;font-family:'Noto Serif';-inkscape-font-specification:'Noto Serif, Heavy';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="-305.64749"
|
||||
y="194.14493"
|
||||
id="text2819"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2817"
|
||||
style="stroke:#ffffff;stroke-width:0"
|
||||
x="-305.64749"
|
||||
y="194.14493" /></text><circle
|
||||
style="fill:#354b5f;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path342"
|
||||
cx="135.46666"
|
||||
cy="135.46666"
|
||||
r="135.46666" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:96.3615px;line-height:0;font-family:'Noto Serif';-inkscape-font-specification:'Noto Serif, Heavy';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="-305.64749"
|
||||
y="194.14493"
|
||||
id="text2819-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2817-5"
|
||||
style="stroke:#ffffff;stroke-width:0"
|
||||
x="-305.64749"
|
||||
y="194.14493" /></text><g
|
||||
aria-label="❯"
|
||||
id="text2827-6"
|
||||
style="font-size:132.452px;line-height:0;font-family:PowerlineSymbols;-inkscape-font-specification:'PowerlineSymbols, Normal';text-align:end;text-anchor:end;fill:#4e94e4;fill-opacity:1;stroke:#ffffff;stroke-width:0"><path
|
||||
d="M 95.096912,209.8167 143.88912,135.46666 95.096912,61.116629 h 32.818568 l 47.92093,74.350031 -47.92093,74.35004 z"
|
||||
id="path2883-2"
|
||||
style="fill:#4e94e4;fill-opacity:1;stroke:#ffffff;stroke-width:0" /></g></g></g></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
|
@ -1,156 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg11"
|
||||
sodipodi:docname="mobile.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="30.03125"
|
||||
inkscape:cx="14.51821"
|
||||
inkscape:cy="11.038502"
|
||||
inkscape:window-width="2544"
|
||||
inkscape:window-height="1363"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg11" />
|
||||
<g
|
||||
id="g11"
|
||||
transform="scale(4)">
|
||||
<g
|
||||
clip-path="url(#clip0_4033_8)"
|
||||
id="g10">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect1"
|
||||
x="0"
|
||||
y="0" />
|
||||
<rect
|
||||
x="60"
|
||||
y="-107"
|
||||
width="35.5569"
|
||||
height="291.86301"
|
||||
transform="rotate(30,60,-107)"
|
||||
fill="#9141ac"
|
||||
id="rect2" />
|
||||
<rect
|
||||
x="90.793198"
|
||||
y="-89.221497"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="rotate(30,90.7932,-89.2215)"
|
||||
fill="#62a0ea"
|
||||
id="rect3" />
|
||||
<rect
|
||||
x="113.888"
|
||||
y="-75.887703"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="rotate(30,113.888,-75.8877)"
|
||||
fill="#57e389"
|
||||
id="rect4" />
|
||||
<rect
|
||||
x="136.983"
|
||||
y="-62.553799"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="rotate(30,136.983,-62.5538)"
|
||||
fill="#f5c211"
|
||||
id="rect5" />
|
||||
<rect
|
||||
x="160.078"
|
||||
y="-49.220001"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="rotate(30,160.078,-49.22)"
|
||||
fill="#ff7800"
|
||||
id="rect6" />
|
||||
<rect
|
||||
x="183.173"
|
||||
y="-35.886101"
|
||||
width="35.5569"
|
||||
height="291.86301"
|
||||
transform="rotate(30,183.173,-35.8861)"
|
||||
fill="#ed333b"
|
||||
id="rect7" />
|
||||
<path
|
||||
d="m 64,23 c 22.6437,0 41,18.3563 41,41 0,22.6437 -18.3563,41 -41,41 -8.6457,0 -16.6648,-2.678 -23.2773,-7.2471 l -9.8018,2.1914 c -1.7167,0.3837 -3.2488,-1.1485 -2.8652,-2.8652 l 2.1904,-9.8027 C 25.6776,80.6641 23,72.6452 23,64 23,41.3563 41.3563,23 64,23 Z"
|
||||
fill="#ffffff"
|
||||
id="path7" />
|
||||
<path
|
||||
d="m 76.2297,62.8668 c 0.4643,0.683 0.461,1.5812 -0.0083,2.2608 L 65.1666,81.1365 C 64.7932,81.6772 64.178,82 63.5209,82 H 58.737 c -1.5974,0 -2.5501,-1.7803 -1.6641,-3.1094 l 9.1875,-13.7812 c 0.4479,-0.6718 0.4479,-1.547 0,-2.2188 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 4.9687 c 0.6623,0 1.2817,0.3279 1.654,0.8757 z"
|
||||
fill="url(#paint0_radial_4033_8)"
|
||||
id="path8"
|
||||
style="fill:url(#paint0_radial_4033_8)" />
|
||||
<mask
|
||||
id="mask0_4033_8"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="56"
|
||||
y="46"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 76.4223,63.1501 c 0.3482,0.5123 0.3457,1.1859 -0.0063,1.6956 L 65.0175,81.3524 C 64.7375,81.7579 64.2761,82 63.7832,82 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.332 l 9.8906,-14.8359 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6641 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6568 z"
|
||||
fill="#2779dd"
|
||||
id="path9" />
|
||||
</mask>
|
||||
<g
|
||||
mask="url(#mask0_4033_8)"
|
||||
id="g9">
|
||||
<rect
|
||||
x="52"
|
||||
y="46"
|
||||
width="17"
|
||||
height="4"
|
||||
fill="#2779dd"
|
||||
id="rect9" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs
|
||||
id="defs11">
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(3.5,24.5214,-15.8099,2.26053,80,52.9904)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11" />
|
||||
</radialGradient>
|
||||
<clipPath
|
||||
id="clip0_4033_8">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect11"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
|
|
@ -1,178 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg11"
|
||||
sodipodi:docname="monochrome.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
inkscape:export-filename="foreground.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="1.240199"
|
||||
inkscape:cx="156.02335"
|
||||
inkscape:cy="321.3194"
|
||||
inkscape:window-width="2544"
|
||||
inkscape:window-height="1363"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg11" />
|
||||
<path
|
||||
d="m 256,92 c 90.5748,0 164,73.4252 164,164 0,90.5748 -73.4252,164 -164,164 -34.5828,0 -66.6592,-10.712 -93.1092,-28.9884 l -39.2072,8.7656 c -6.8668,1.5348 -12.9952,-4.594 -11.4608,-11.4608 l 8.7616,-39.2108 C 102.7104,322.6564 92,290.5808 92,256 92,165.4252 165.4252,92 256,92 Z"
|
||||
fill="#ffffff"
|
||||
id="path7"
|
||||
style="stroke-width:4"
|
||||
clip-path="url(#clipPath1)"
|
||||
inkscape:path-effect="#path-effect1" />
|
||||
<defs
|
||||
id="defs11">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
message=""
|
||||
id="path-effect1"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false" />
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(14,98.0856,-63.2396,9.04212,320,211.9616)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11" />
|
||||
</radialGradient>
|
||||
<mask
|
||||
id="mask0_4033_8"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="56"
|
||||
y="46"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 76.4223,63.1501 c 0.3482,0.5123 0.3457,1.1859 -0.0063,1.6956 L 65.0175,81.3524 C 64.7375,81.7579 64.2761,82 63.7832,82 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.332 l 9.8906,-14.8359 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6641 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6568 z"
|
||||
fill="#2779dd"
|
||||
id="path9" />
|
||||
</mask>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath11">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect12"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath12">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect13"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath13">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect14"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath14">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect15"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath15">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect16"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath16">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect17"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath1">
|
||||
<path
|
||||
d="m 304.9188,251.4672 c 1.8572,2.732 1.844,6.3248 -0.0332,9.0432 L 260.6664,324.546 C 259.1728,326.7088 256.712,328 254.0836,328 H 234.948 c -6.3896,0 -10.2004,-7.1212 -6.6564,-12.4376 l 36.75,-55.1248 c 1.7916,-2.6872 1.7916,-6.188 0,-8.8752 l -36.75,-55.1248 C 224.7476,191.1212 228.5584,184 234.948,184 h 19.8748 c 2.6492,0 5.1268,1.3116 6.616,3.5028 z"
|
||||
fill="url(#paint0_radial_4033_8)"
|
||||
id="path1"
|
||||
style="display:none;fill:url(#radialGradient1);stroke-width:4" />
|
||||
<path
|
||||
id="lpe_path-effect1"
|
||||
style="fill:url(#radialGradient1);stroke-width:4"
|
||||
class="powerclip"
|
||||
d="M 87,87 H 425 V 425 H 87 Z m 217.9188,164.4672 -43.48,-63.9644 C 259.9496,185.3116 257.472,184 254.8228,184 H 234.948 c -6.3896,0 -10.2004,7.1212 -6.6564,12.4376 l 36.75,55.1248 c 1.7916,2.6872 1.7916,6.188 0,8.8752 l -36.75,55.1248 C 224.7476,320.8788 228.5584,328 234.948,328 h 19.1356 c 2.6284,0 5.0892,-1.2912 6.5828,-3.454 l 44.2192,-64.0356 c 1.8772,-2.7184 1.8904,-6.3112 0.0332,-9.0432 z" />
|
||||
</clipPath>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#paint0_radial_4033_8"
|
||||
id="radialGradient1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(14,98.0856,-63.2396,9.04212,320,211.9616)"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1" />
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 616 KiB After Width: | Height: | Size: 423 KiB |
|
Before Width: | Height: | Size: 616 KiB After Width: | Height: | Size: 425 KiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 130 KiB |
93
flake.lock
generated
|
|
@ -5,11 +5,11 @@
|
|||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1785627969,
|
||||
"narHash": "sha256-4dtXQk/NMePegK/nWp5NSeuZKLATItOq61lpEvmXqGw=",
|
||||
"lastModified": 1767609335,
|
||||
"narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "427bf4bd9435fdf21321c8cc628c24efc14c0f7a",
|
||||
"rev": "250481aafeb741edfe23d29195671c19b36b6dca",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -18,54 +18,17 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix2flatpak": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1774860670,
|
||||
"narHash": "sha256-YjJkQrvxrErXtfDi3obUn6rNmkA+CIAZ3f5NgL5xuYE=",
|
||||
"owner": "neobrain",
|
||||
"repo": "nix2flatpak",
|
||||
"rev": "61d68e21e3fbc2d57590051f48736bea271f4aba",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "neobrain",
|
||||
"repo": "nix2flatpak",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1773389992,
|
||||
"narHash": "sha256-wvfdLLWJ2I9oEpDd9PfMA8osfIZicoQ5MT1jIwNs9Tk=",
|
||||
"owner": "NixOS",
|
||||
"lastModified": 1767640445,
|
||||
"narHash": "sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i+bwD6XxMb8A=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c06b4ae3d6599a672a6210b7021d699c351eebda",
|
||||
"rev": "9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
|
|
@ -73,11 +36,11 @@
|
|||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1785031560,
|
||||
"narHash": "sha256-OmshNvn2vupOFpYinLUu+1Dnpu4n7Q5N3ggGVNHpkUI=",
|
||||
"lastModified": 1765674936,
|
||||
"narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "0e79af5e3d4dcfcd676ab5ba3f95d2e3352e078c",
|
||||
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -86,42 +49,10 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1785967620,
|
||||
"narHash": "sha256-IItrdb7Puk05RqOBWZYFC5X6Wl1sJmCfh5MWVHw5iMM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b7c2ada94fe99c15b0dbcf4d11fd7850b957a436",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"nix2flatpak": "nix2flatpak",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
45
flake.nix
|
|
@ -2,10 +2,8 @@
|
|||
description = "Nexus Flutter Flake";
|
||||
|
||||
inputs = {
|
||||
self.submodules = true;
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
nix2flatpak.url = "github:neobrain/nix2flatpak";
|
||||
};
|
||||
|
||||
outputs =
|
||||
|
|
@ -35,43 +33,36 @@
|
|||
_module.args.pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config = {
|
||||
permittedInsecurePackages = [ "olm-3.2.16" ];
|
||||
android_sdk.accept_license = true;
|
||||
allowUnfree = true;
|
||||
};
|
||||
};
|
||||
|
||||
packages =
|
||||
devShells =
|
||||
let
|
||||
default = pkgs.callPackage ./linux/nix/pkg {
|
||||
src = self;
|
||||
packages = with pkgs; [
|
||||
go
|
||||
olm
|
||||
git
|
||||
];
|
||||
|
||||
env = {
|
||||
LIBCLANG_PATH = lib.makeLibraryPath [ pkgs.libclang ];
|
||||
LD_LIBRARY_PATH = "./build/native_assets/linux:${lib.makeLibraryPath [ pkgs.zlib ]}";
|
||||
CPATH = lib.makeSearchPath "include" [ pkgs.glibc.dev ];
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit default;
|
||||
|
||||
flatpak = inputs.nix2flatpak.lib.${system}.mkFlatpak {
|
||||
appName = "Nexus";
|
||||
developer = "QuadRadical";
|
||||
appId = "nexus.federated.nexus";
|
||||
package = default;
|
||||
runtime = "org.gnome.Platform/49";
|
||||
permissions = {
|
||||
share = [ "network" ];
|
||||
sockets = [
|
||||
"pulseaudio"
|
||||
"fallback-x11"
|
||||
"wayland"
|
||||
];
|
||||
devices = [ "dri" ];
|
||||
};
|
||||
default = pkgs.mkShell {
|
||||
inherit env;
|
||||
packages = packages ++ [
|
||||
pkgs.flutter
|
||||
];
|
||||
};
|
||||
|
||||
gomuks = pkgs.callPackage ./linux/nix/pkg/gomuks.nix {
|
||||
src = self;
|
||||
};
|
||||
nix = pkgs.mkShell { inherit packages env; };
|
||||
};
|
||||
|
||||
devShells.default = pkgs.callPackage ./linux/nix/devshell.nix { };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
1
gomuks
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 9444dd293664c300c6e710bb6cddcd9c6cab365d
|
||||
181
hook/build.dart
|
|
@ -1,193 +1,40 @@
|
|||
import "dart:io";
|
||||
import "package:collection/collection.dart";
|
||||
import "package:hooks/hooks.dart";
|
||||
import "package:code_assets/code_assets.dart";
|
||||
import "package:nexus/helpers/extensions/get_xcode_sdk.dart";
|
||||
import "package:path/path.dart";
|
||||
|
||||
Future<void> main(List<String> args) => build(args, (input, output) async {
|
||||
if (!input.config.buildCodeAssets) return;
|
||||
final codeConfig = input.config.code;
|
||||
final targetOS = codeConfig.targetOS;
|
||||
final targetArch = codeConfig.targetArchitecture;
|
||||
final buildDir = input.packageRoot.resolve("src/");
|
||||
if (await File(buildDir.resolve("lock").toFilePath()).exists()) return;
|
||||
|
||||
final targetOS = input.config.code.targetOS;
|
||||
String libFileName;
|
||||
Map<String, String> extraEnv = {};
|
||||
IOSSdk? iosSdk;
|
||||
String? iosSdkPath;
|
||||
String? iosTargetTriple;
|
||||
switch (targetOS) {
|
||||
case OS.linux:
|
||||
libFileName = "libgomuks.so";
|
||||
break;
|
||||
case OS.iOS:
|
||||
// Go only supports buildmode=c-archive for ios, not c-shared, so the
|
||||
// archive built below gets linked into a dylib via a separate clang
|
||||
// invocation before being registered as a normal asset like macOS.
|
||||
libFileName = "libgomuks.dylib";
|
||||
final iosConfig = codeConfig.iOS;
|
||||
iosSdk = iosConfig.targetSdk;
|
||||
final minVersion = iosConfig.targetVersion;
|
||||
iosSdkPath = await getXCodeTool(sdkType: iosSdk.type);
|
||||
|
||||
final archTriple = switch (targetArch) {
|
||||
Architecture.arm64 => "arm64",
|
||||
Architecture.x64 => "x86_64",
|
||||
_ => throw UnsupportedError(
|
||||
"Unsupported iOS architecture: $targetArch",
|
||||
),
|
||||
};
|
||||
|
||||
iosTargetTriple = iosSdk == IOSSdk.iPhoneSimulator
|
||||
? "$archTriple-apple-ios$minVersion.0-simulator"
|
||||
: "$archTriple-apple-ios$minVersion.0";
|
||||
extraEnv = {
|
||||
"GOOS": "ios",
|
||||
"CC": await getXCodeTool(sdkType: iosSdk.type, findTool: "clang"),
|
||||
"CGO_CFLAGS": "-isysroot $iosSdkPath -target $iosTargetTriple",
|
||||
"CGO_LDFLAGS": "-isysroot $iosSdkPath -target $iosTargetTriple",
|
||||
};
|
||||
break;
|
||||
case OS.macOS:
|
||||
libFileName = "libgomuks.dylib";
|
||||
extraEnv = {
|
||||
"SDKROOT": await getXCodeTool(),
|
||||
"MACOSX_DEPLOYMENT_TARGET": codeConfig.macOS.targetVersion.toString(),
|
||||
};
|
||||
break;
|
||||
case OS.windows:
|
||||
libFileName = "libgomuks.dll";
|
||||
break;
|
||||
case OS.android:
|
||||
libFileName = "libgomuks.so";
|
||||
|
||||
final targetNdkApi = codeConfig.android.targetNdkApi;
|
||||
|
||||
Future<String?> findNdkFromSdk() async {
|
||||
final androidHome =
|
||||
Platform.environment["ANDROID_HOME"] ??
|
||||
Platform.environment["ANDROID_SDK_ROOT"];
|
||||
if (androidHome == null) return null;
|
||||
|
||||
final ndkDir = Directory(join(androidHome, "ndk"));
|
||||
if (!await ndkDir.exists()) return null;
|
||||
|
||||
final versions = await ndkDir.list().toList();
|
||||
return versions.sortedBy((file) => file.path).lastOrNull?.path;
|
||||
}
|
||||
|
||||
final ndkHome =
|
||||
Platform.environment["ANDROID_NDK_HOME"] ??
|
||||
Platform.environment["ANDROID_NDK_ROOT"] ??
|
||||
Platform.environment["NDK_HOME"] ??
|
||||
await findNdkFromSdk();
|
||||
|
||||
if (ndkHome == null) {
|
||||
throw Exception(
|
||||
"Could not find Android NDK. Set ANDROID_NDK_HOME or install via sdkmanager.",
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Someone please give me a way to detect host architecture so I can change this
|
||||
final hostTag =
|
||||
Platform.environment["ANDROID_HOST_TAG"] ??
|
||||
"${Platform.operatingSystem}-x86_64";
|
||||
final ccTriple = switch (targetArch) {
|
||||
Architecture.arm64 => "aarch64-linux-android",
|
||||
Architecture.arm => "armv7a-linux-androideabi",
|
||||
Architecture.x64 => "x86_64-linux-android",
|
||||
Architecture.ia32 => "i686-linux-android",
|
||||
_ => throw UnsupportedError(
|
||||
"Unsupported Android architecture: $targetArch",
|
||||
),
|
||||
};
|
||||
final cc =
|
||||
"$ndkHome/toolchains/llvm/prebuilt/$hostTag/bin/$ccTriple$targetNdkApi-clang";
|
||||
|
||||
extraEnv = {"GOOS": "android", "CC": cc};
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError("Unsupported OS: $targetOS");
|
||||
}
|
||||
|
||||
var libFile = input.packageRoot.resolve(libFileName);
|
||||
final gomuksBuildDir = input.packageRoot.resolve("gomuks/");
|
||||
final gomuksBuildDir = buildDir.resolve("gomuks/");
|
||||
final libFile = gomuksBuildDir.resolve(libFileName);
|
||||
|
||||
if (!(await File.fromUri(libFile).exists())) {
|
||||
final buildDir = input.packageRoot.resolve("build/");
|
||||
libFile = buildDir.resolve("${targetArch.name}/$libFileName");
|
||||
print("Building Gomuks shared library $libFileName from source...");
|
||||
final result = await Process.run("go", [
|
||||
"build",
|
||||
"-o",
|
||||
libFile.path,
|
||||
"-buildmode=c-shared",
|
||||
], workingDirectory: gomuksBuildDir.resolve("source/pkg/ffi/").toFilePath());
|
||||
|
||||
final tags = [
|
||||
"sqlite_fts5",
|
||||
"goolm",
|
||||
// goheif/dav1d is not supported on Android or iOS, would need to be fixed upstream
|
||||
if (targetOS == OS.android || targetOS == OS.iOS) "noheic",
|
||||
].join(",");
|
||||
|
||||
final archiveFile = targetOS == OS.iOS
|
||||
? buildDir.resolve("${targetArch.name}/libgomuks.a")
|
||||
: libFile;
|
||||
print(
|
||||
"Building Gomuks shared library $libFileName (${targetOS.name}/${targetArch.name}) to ${archiveFile.path}...",
|
||||
);
|
||||
final result = await Process.run(
|
||||
"go",
|
||||
[
|
||||
"build",
|
||||
"-tags",
|
||||
tags,
|
||||
"-o",
|
||||
archiveFile.path,
|
||||
"-buildmode=${targetOS == OS.iOS ? "c-archive" : "c-shared"}",
|
||||
],
|
||||
workingDirectory: gomuksBuildDir.resolve("pkg/ffi/").toFilePath(),
|
||||
environment: {
|
||||
"CGO_ENABLED": "1",
|
||||
"GOARCH": switch (targetArch) {
|
||||
Architecture.arm64 => "arm64",
|
||||
Architecture.arm => "arm",
|
||||
Architecture.x64 => "amd64",
|
||||
Architecture.ia32 => "386",
|
||||
_ => throw UnsupportedError("Unsupported architecture: $targetArch"),
|
||||
},
|
||||
...extraEnv,
|
||||
},
|
||||
);
|
||||
|
||||
if (result.exitCode != 0) {
|
||||
throw Exception(
|
||||
"Failed to build Gomuks shared library\n${result.stderr}",
|
||||
);
|
||||
}
|
||||
|
||||
if (targetOS == OS.iOS) {
|
||||
print("Linking $archiveFile into $libFile...");
|
||||
final linkResult = await Process.run("xcrun", [
|
||||
"--sdk",
|
||||
iosSdk!.type,
|
||||
"clang",
|
||||
"-dynamiclib",
|
||||
"-isysroot",
|
||||
iosSdkPath!,
|
||||
"-target",
|
||||
iosTargetTriple!,
|
||||
"-install_name",
|
||||
"@rpath/libgomuks.dylib",
|
||||
"-framework",
|
||||
"Security",
|
||||
"-framework",
|
||||
"CoreFoundation",
|
||||
"-framework",
|
||||
"SystemConfiguration",
|
||||
"-force_load",
|
||||
archiveFile.path,
|
||||
"-o",
|
||||
libFile.path,
|
||||
]);
|
||||
if (linkResult.exitCode != 0) {
|
||||
throw Exception("Failed to link Gomuks dylib\n${linkResult.stderr}");
|
||||
}
|
||||
}
|
||||
if (result.exitCode != 0) {
|
||||
throw Exception("Failed to build Gomuks shared library\n${result.stderr}");
|
||||
}
|
||||
|
||||
final generatedFile = "src/third_party/gomuks.g.dart";
|
||||
|
|
|
|||
|
|
@ -2,23 +2,25 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>nexus.federated.Nexus</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>15.5</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
30
ios/Podfile
|
|
@ -1,7 +1,4 @@
|
|||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '13.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
platform :ios, 16
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
|
|
@ -29,15 +26,30 @@ flutter_ios_podfile_setup
|
|||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
|
||||
use_modular_headers!
|
||||
|
||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||
target 'RunnerTests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_ios_build_settings(target)
|
||||
target.build_configurations.each do |config|
|
||||
if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] == '8.0'
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
|
||||
end
|
||||
end
|
||||
flutter_additional_ios_build_settings target
|
||||
end
|
||||
|
||||
################ Awesome Notifications pod modification 1 ###################
|
||||
awesome_pod_file = File.expand_path(File.join('plugins', 'awesome_notifications', 'ios', 'Scripts', 'AwesomePodFile'), '.symlinks')
|
||||
require awesome_pod_file
|
||||
update_awesome_pod_build_settings(installer)
|
||||
################ Awesome Notifications pod modification 1 ###################
|
||||
end
|
||||
|
||||
################ Awesome Notifications pod modification 2 ###################
|
||||
awesome_pod_file = File.expand_path(File.join('plugins', 'awesome_notifications', 'ios', 'Scripts', 'AwesomePodFile'), '.symlinks')
|
||||
require awesome_pod_file
|
||||
update_awesome_main_target_settings('Runner', File.dirname(File.realpath(__FILE__)), flutter_root)
|
||||
################ Awesome Notifications pod modification 2 ###################
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
PODS:
|
||||
- Flutter (1.0.0)
|
||||
- media_kit_libs_ios_video (1.0.4):
|
||||
- Flutter
|
||||
- media_kit_video (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- Flutter (from `Flutter`)
|
||||
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
||||
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
media_kit_libs_ios_video:
|
||||
:path: ".symlinks/plugins/media_kit_libs_ios_video/ios"
|
||||
media_kit_video:
|
||||
:path: ".symlinks/plugins/media_kit_video/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||
|
||||
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
||||
|
||||
COCOAPODS: 1.17.0
|
||||
|
|
@ -8,28 +8,14 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
2ADFEE6C745FFB2100CC9AFD /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8156A45F510382D558AED93A /* Pods_RunnerTests.framework */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3965FF1D950A2B2E051F6219 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E598BBDD2ED0112E344B590 /* Pods_Runner.framework */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; };
|
||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
|
||||
88D55A5F1C7625122EBEE29D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82F9A3759658343C81A0EA4C /* Pods_Runner.framework */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
||||
remoteInfo = Runner;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
|
|
@ -46,19 +32,12 @@
|
|||
/* Begin PBXFileReference section */
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
22DE4310DAFBE211CDF700B1 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
363A89F6FA09BCCBDED440CE /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
63516CF65A79A5DDDE64B0D1 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
5E598BBDD2ED0112E344B590 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6A2D47C573B065AD356C7183 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
8156A45F510382D558AED93A /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
82F9A3759658343C81A0EA4C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
|
@ -66,67 +45,35 @@
|
|||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
AEB96D8976BD46D6860C7041 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B8B599FDB72E4713FB7B5A44 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
FE5E4162842555A83F8A7FD7 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
CA00A9F43BB1AB7D908E180A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
DFFCB3F45BF495277AE4D3EE /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
8C0A36760DA8B873D8F6DDCE /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2ADFEE6C745FFB2100CC9AFD /* Pods_RunnerTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
|
||||
88D55A5F1C7625122EBEE29D /* Pods_Runner.framework in Frameworks */,
|
||||
3965FF1D950A2B2E051F6219 /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
1CFFAE23B502BCCEB2B191A3 /* Pods */ = {
|
||||
7226BEAE3D25CA120A434CC9 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
AEB96D8976BD46D6860C7041 /* Pods-Runner.debug.xcconfig */,
|
||||
363A89F6FA09BCCBDED440CE /* Pods-Runner.release.xcconfig */,
|
||||
22DE4310DAFBE211CDF700B1 /* Pods-Runner.profile.xcconfig */,
|
||||
B8B599FDB72E4713FB7B5A44 /* Pods-RunnerTests.debug.xcconfig */,
|
||||
FE5E4162842555A83F8A7FD7 /* Pods-RunnerTests.release.xcconfig */,
|
||||
63516CF65A79A5DDDE64B0D1 /* Pods-RunnerTests.profile.xcconfig */,
|
||||
DFFCB3F45BF495277AE4D3EE /* Pods-Runner.debug.xcconfig */,
|
||||
CA00A9F43BB1AB7D908E180A /* Pods-Runner.release.xcconfig */,
|
||||
6A2D47C573B065AD356C7183 /* Pods-Runner.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */,
|
||||
);
|
||||
path = RunnerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
594EB1F65336CF9C7958F6FA /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
82F9A3759658343C81A0EA4C /* Pods_Runner.framework */,
|
||||
8156A45F510382D558AED93A /* Pods_RunnerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
|
|
@ -141,9 +88,8 @@
|
|||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
1CFFAE23B502BCCEB2B191A3 /* Pods */,
|
||||
594EB1F65336CF9C7958F6FA /* Frameworks */,
|
||||
7226BEAE3D25CA120A434CC9 /* Pods */,
|
||||
E396C277672D83FCFDB51CCB /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
|
@ -151,7 +97,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -166,55 +111,41 @@
|
|||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */,
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E396C277672D83FCFDB51CCB /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5E598BBDD2ED0112E344B590 /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
331C8080294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
EE82EC529EB6C0F1FA480659 /* [CP] Check Pods Manifest.lock */,
|
||||
331C807D294A63A400263BE5 /* Sources */,
|
||||
331C807F294A63A400263BE5 /* Resources */,
|
||||
8C0A36760DA8B873D8F6DDCE /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */,
|
||||
);
|
||||
name = RunnerTests;
|
||||
productName = RunnerTests;
|
||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
0830C6758DA3ECA81FB12386 /* [CP] Check Pods Manifest.lock */,
|
||||
A3B5CB395514F4BF9CDF304E /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
1D165FDFB9D0D939B041966D /* [CP] Embed Pods Frameworks */,
|
||||
C3C8545BDAC52D360D298A29 /* [CP] Embed Pods Frameworks */,
|
||||
F46F66CC32F585BBF2FB675E /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
packageProductDependencies = (
|
||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
|
||||
);
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
|
|
@ -229,10 +160,6 @@
|
|||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C8080294A63A400263BE5 = {
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||
};
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
LastSwiftMigration = 1100;
|
||||
|
|
@ -248,27 +175,16 @@
|
|||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
packageReferences = (
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
|
||||
);
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
331C807F294A63A400263BE5 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -283,45 +199,6 @@
|
|||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
0830C6758DA3ECA81FB12386 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
1D165FDFB9D0D939B041966D /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
|
|
@ -353,7 +230,7 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
EE82EC529EB6C0F1FA480659 /* [CP] Check Pods Manifest.lock */ = {
|
||||
A3B5CB395514F4BF9CDF304E /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
|
@ -368,44 +245,61 @@
|
|||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
C3C8545BDAC52D360D298A29 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F46F66CC32F585BBF2FB675E /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
331C807D294A63A400263BE5 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
|
|
@ -430,7 +324,6 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
|
@ -460,7 +353,6 @@
|
|||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
|
|
@ -482,10 +374,13 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = AppIcon;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = PK66NJM372;
|
||||
DEVELOPMENT_TEAM = P3ZD9TNSKZ;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
@ -500,61 +395,10 @@
|
|||
};
|
||||
name = Profile;
|
||||
};
|
||||
331C8088294A63A400263BE5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B8B599FDB72E4713FB7B5A44 /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.nexus.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
331C8089294A63A400263BE5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = FE5E4162842555A83F8A7FD7 /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.nexus.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
331C808A294A63A400263BE5 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 63516CF65A79A5DDDE64B0D1 /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.nexus.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
|
@ -584,7 +428,6 @@
|
|||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
|
|
@ -611,7 +454,6 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
|
@ -641,7 +483,6 @@
|
|||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
|
|
@ -665,10 +506,13 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = AppIcon;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = PK66NJM372;
|
||||
DEVELOPMENT_TEAM = P3ZD9TNSKZ;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
@ -688,10 +532,13 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = AppIcon;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = PK66NJM372;
|
||||
DEVELOPMENT_TEAM = P3ZD9TNSKZ;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
@ -709,16 +556,6 @@
|
|||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
331C8088294A63A400263BE5 /* Debug */,
|
||||
331C8089294A63A400263BE5 /* Release */,
|
||||
331C808A294A63A400263BE5 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
@ -740,20 +577,6 @@
|
|||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCLocalSwiftPackageReference section */
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
|
||||
isa = XCLocalSwiftPackageReference;
|
||||
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
|
||||
};
|
||||
/* End XCLocalSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = FlutterGeneratedPluginSwiftPackage;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,24 +5,6 @@
|
|||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<PreActions>
|
||||
<ExecutionAction
|
||||
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
|
||||
<ActionContent
|
||||
title = "Run Prepare Flutter Framework Script"
|
||||
scriptText = "/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" prepare ">
|
||||
<EnvironmentBuildable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</EnvironmentBuildable>
|
||||
</ActionContent>
|
||||
</ExecutionAction>
|
||||
</PreActions>
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
import Flutter
|
||||
import UIKit
|
||||
import Flutter
|
||||
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
|
||||
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 176 KiB |
|
Before Width: | Height: | Size: 846 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 16 KiB |
|
|
@ -3,7 +3,7 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<false/>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
|
|
@ -22,40 +22,30 @@
|
|||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>nexus.federated.nexus</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>file</string>
|
||||
<string>https</string>
|
||||
<string>http</string>
|
||||
<string>mailto</string>
|
||||
<string>tel</string>
|
||||
</array>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneClassName</key>
|
||||
<string>UIWindowScene</string>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>flutter</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
<key>UISceneStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>This app needs camera access to scan asset QR codes</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>This app doesn't use your microphone.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>This app doesn't use your photo library.</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
import Flutter
|
||||
import UIKit
|
||||
|
||||
class SceneDelegate: FlutterSceneDelegate {
|
||||
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import Flutter
|
||||
import UIKit
|
||||
import XCTest
|
||||
|
||||
class RunnerTests: XCTestCase {
|
||||
|
||||
func testExample() {
|
||||
// If you add code to the Runner application, consider adding tests here.
|
||||
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
import "dart:convert";
|
||||
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/models/account_data.dart";
|
||||
|
||||
class AccountDataController extends Notifier<AccountData> {
|
||||
@override
|
||||
AccountData build() => .new();
|
||||
|
||||
void update(IMap<String, IMap<String, dynamic>> newAccountData) =>
|
||||
state = .fromJson({
|
||||
...json.decode(json.encode(state.toJson())),
|
||||
...newAccountData
|
||||
.map((key, value) => MapEntry(key, value["content"]))
|
||||
.unlock,
|
||||
});
|
||||
|
||||
static final provider = NotifierProvider<AccountDataController, AccountData>(
|
||||
AccountDataController.new,
|
||||
);
|
||||
}
|
||||
16
lib/controllers/account_data_controller.dart
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/models/account_data.dart";
|
||||
|
||||
class AccountDataController extends Notifier<IMap<String, AccountData>> {
|
||||
@override
|
||||
IMap<String, AccountData> build() => const IMap.empty();
|
||||
|
||||
void update(IMap<String, AccountData> newData) =>
|
||||
state = IMap({...state.unlock, ...newData.unlock});
|
||||
|
||||
static final provider =
|
||||
NotifierProvider<AccountDataController, IMap<String, AccountData>>(
|
||||
AccountDataController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
import "package:file_selector/file_selector.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
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);
|
||||
|
||||
@override
|
||||
Null build() => null;
|
||||
|
||||
Future<void> add(XFile file) async {
|
||||
final filename = basename(file.path);
|
||||
state = (filename, null);
|
||||
|
||||
final isEncrypted = ref.read(
|
||||
RoomsController.provider.select(
|
||||
(value) =>
|
||||
value[roomId]?.state[EventType.encryption.type]?.isNotEmpty == true,
|
||||
),
|
||||
);
|
||||
|
||||
final content = await ref
|
||||
.watch(ClientController.provider.notifier)
|
||||
.uploadMedia(.new(path: file.path, encrypt: isEncrypted));
|
||||
|
||||
state = (filename, content);
|
||||
}
|
||||
|
||||
static final provider = NotifierProvider.family
|
||||
.autoDispose<AttachmentController, (String, MessageContent?)?, String>(
|
||||
AttachmentController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
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);
|
||||
|
||||
@override
|
||||
Future<OAuthAuthCodeResponse> build() async => ref
|
||||
.watch(ClientController.provider.notifier)
|
||||
.getAuthUrl(
|
||||
.new(
|
||||
homeserverUrl: homeserver,
|
||||
redirectUri: .new(scheme: "nexus.federated.nexus", path: "/"),
|
||||
responseMode: .query,
|
||||
scopes: .new([Scope.clientApi, Scope.device]),
|
||||
clientId: await ref.watch(
|
||||
ClientIdController.provider(homeserver).future,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
static final provider = AsyncNotifierProvider.family
|
||||
.autoDispose<AuthUrlController, OAuthAuthCodeResponse, Uri>(
|
||||
AuthUrlController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
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);
|
||||
|
||||
@override
|
||||
Future<MembershipContent> build() async {
|
||||
final member = await ref.watch(
|
||||
UserController.provider(
|
||||
.new(roomId: event.roomId, userId: event.sender),
|
||||
).future,
|
||||
);
|
||||
|
||||
return .new(
|
||||
status: member.status,
|
||||
avatarUrl: event.pmp?.avatarUrl ?? member.avatarUrl,
|
||||
displayName: event.pmp?.displayName ?? member.displayName,
|
||||
);
|
||||
}
|
||||
|
||||
static final provider =
|
||||
AsyncNotifierProvider.family<AuthorController, MembershipContent, Event>(
|
||||
AuthorController.new,
|
||||
);
|
||||
}
|
||||
44
lib/controllers/author_controller.dart
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import "dart:async";
|
||||
import "package:collection/collection.dart";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/members_controller.dart";
|
||||
import "package:nexus/models/configs/author_config.dart";
|
||||
import "package:nexus/models/membership.dart";
|
||||
|
||||
class AuthorController extends AsyncNotifier<Membership> {
|
||||
final AuthorConfig config;
|
||||
AuthorController(this.config);
|
||||
|
||||
@override
|
||||
Future<Membership> build() async {
|
||||
var member = await ref.watch(
|
||||
MembersController.provider(config.room).selectAsync(
|
||||
(value) => value.firstWhereOrNull(
|
||||
(membership) => membership.userId == config.message.authorId,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final pmp = config.message.metadata?["pmp"] == null
|
||||
? null
|
||||
: Membership.fromContent(
|
||||
IMap(config.message.metadata?["pmp"]),
|
||||
config.message.authorId,
|
||||
);
|
||||
|
||||
return Membership(
|
||||
avatarUrl: pmp?.avatarUrl ?? member?.avatarUrl,
|
||||
displayName:
|
||||
pmp?.displayName ??
|
||||
member?.displayName ??
|
||||
config.message.authorId.substring(1).split(":").first,
|
||||
userId: config.message.authorId,
|
||||
);
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider.family
|
||||
.autoDispose<AuthorController, Membership, AuthorConfig>(
|
||||
AuthorController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,327 +0,0 @@
|
|||
import "dart:ffi";
|
||||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
import "dart:math";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:ffi/ffi.dart";
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:nexus/controllers/account_data.dart";
|
||||
import "package:nexus/controllers/client_state.dart";
|
||||
import "package:nexus/controllers/init_complete.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/controllers/space_edges.dart";
|
||||
import "package:nexus/controllers/sync_status.dart";
|
||||
import "package:nexus/controllers/top_level_spaces.dart";
|
||||
import "package:nexus/helpers/extensions/gomuks_buffer.dart";
|
||||
import "package:nexus/main.dart";
|
||||
import "package:nexus/models/content/message.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/oauth_auth_code_response.dart";
|
||||
import "package:nexus/models/open_graph_data.dart";
|
||||
import "package:nexus/models/paginate.dart";
|
||||
import "package:nexus/models/requests/download_media.dart";
|
||||
import "package:nexus/models/requests/get_event.dart";
|
||||
import "package:nexus/models/requests/get_related_events.dart";
|
||||
import "package:nexus/models/requests/get_room_state.dart";
|
||||
import "package:nexus/models/requests/join_room.dart";
|
||||
import "package:nexus/models/profile_response.dart";
|
||||
import "package:nexus/models/requests/oauth/exchange_token.dart";
|
||||
import "package:nexus/models/requests/oauth/get_auth_url.dart";
|
||||
import "package:nexus/models/requests/oauth/register_client.dart";
|
||||
import "package:nexus/models/requests/paginate.dart";
|
||||
import "package:nexus/models/requests/redact_event.dart";
|
||||
import "package:nexus/models/requests/report.dart";
|
||||
import "package:nexus/models/requests/send_event.dart";
|
||||
import "package:nexus/models/requests/send_message.dart";
|
||||
import "package:nexus/models/requests/set_account_data.dart";
|
||||
import "package:nexus/models/requests/set_membership.dart";
|
||||
import "package:nexus/models/requests/set_state.dart";
|
||||
import "package:nexus/models/requests/upload_media.dart";
|
||||
import "package:nexus/models/room.dart";
|
||||
import "package:nexus/models/room_summary.dart";
|
||||
import "package:nexus/models/spec_versions_response.dart";
|
||||
import "package:nexus/models/sync_data.dart";
|
||||
import "package:nexus/src/third_party/gomuks.g.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:path_provider/path_provider.dart";
|
||||
|
||||
class ClientController extends AsyncNotifier<int> {
|
||||
@override
|
||||
Future<int> build() async {
|
||||
final Pointer<Char> root;
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
final dir = await getApplicationSupportDirectory();
|
||||
root = "${dir.path}/gomuks".toNativeUtf8().cast();
|
||||
} else {
|
||||
root = nullptr.cast();
|
||||
}
|
||||
|
||||
final handle = GomuksInit(root);
|
||||
|
||||
final callable =
|
||||
NativeCallable<
|
||||
Void Function(Pointer<Char>, Int64, GomuksOwnedBuffer)
|
||||
>.listener((
|
||||
Pointer<Char> command,
|
||||
int requestId,
|
||||
GomuksOwnedBuffer data,
|
||||
) {
|
||||
try {
|
||||
final muksEventType = command.cast<Utf8>().toDartString();
|
||||
debugPrint("Handling $muksEventType...");
|
||||
final decodedMuksEvent = data.toJson();
|
||||
|
||||
switch (muksEventType) {
|
||||
case "client_state":
|
||||
ref
|
||||
.watch(ClientStateController.provider.notifier)
|
||||
.set(.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "sync_status":
|
||||
ref
|
||||
.watch(SyncStatusController.provider.notifier)
|
||||
.set(.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "init_complete":
|
||||
ref.watch(InitCompleteController.provider.notifier).complete();
|
||||
break;
|
||||
case "send_complete":
|
||||
final event = Event.fromJson(decodedMuksEvent["event"]);
|
||||
ref
|
||||
.watch(RoomsController.provider.notifier)
|
||||
.update(
|
||||
.new({
|
||||
event.roomId: .new(events: .new({event.rowId: event})),
|
||||
}),
|
||||
.new(),
|
||||
);
|
||||
|
||||
break;
|
||||
case "sync_complete":
|
||||
final syncData = SyncData.fromJson(decodedMuksEvent);
|
||||
final roomProvider = RoomsController.provider;
|
||||
final accountDataProvider = AccountDataController.provider;
|
||||
|
||||
if (syncData.clearState) {
|
||||
ref.invalidate(roomProvider);
|
||||
ref.invalidate(accountDataProvider);
|
||||
}
|
||||
|
||||
ref
|
||||
.watch(roomProvider.notifier)
|
||||
.update(syncData.rooms, syncData.leftRooms);
|
||||
ref
|
||||
.watch(accountDataProvider.notifier)
|
||||
.update(syncData.accountData);
|
||||
|
||||
if (syncData.topLevelSpaces != null) {
|
||||
ref
|
||||
.watch(TopLevelSpacesController.provider.notifier)
|
||||
.set(syncData.topLevelSpaces!);
|
||||
}
|
||||
|
||||
if (syncData.spaceEdges != null) {
|
||||
ref
|
||||
.watch(SpaceEdgesController.provider.notifier)
|
||||
.set(syncData.spaceEdges!);
|
||||
}
|
||||
|
||||
// ref
|
||||
// .watch(SyncStatusController.provider.notifier)
|
||||
// .set(SyncStatus.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
default:
|
||||
debugPrint("Unhandled event: $muksEventType");
|
||||
}
|
||||
debugPrint("Finished handling $muksEventType...");
|
||||
} catch (error, stackTrace) {
|
||||
if (kDebugMode) {
|
||||
debugPrintStack(stackTrace: stackTrace, label: error.toString());
|
||||
rethrow;
|
||||
} else {
|
||||
showError(error, stackTrace);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ref.onDispose(() => GomuksDestroy(handle));
|
||||
ref.onDispose(callable.close);
|
||||
|
||||
final errorCode = GomuksStart(handle, callable.nativeFunction);
|
||||
|
||||
if (errorCode == 0) return handle;
|
||||
throw Exception("GomuksStart returned error code $errorCode");
|
||||
}
|
||||
|
||||
Future<dynamic> _sendCommand(
|
||||
String command, [
|
||||
Map<String, dynamic> data = const {},
|
||||
]) async {
|
||||
final bufferPointer = data.toGomuksBufferPtr();
|
||||
final handle = await future;
|
||||
final response = await Isolate.run(
|
||||
() => GomuksSubmitCommand(
|
||||
handle,
|
||||
command.toNativeUtf8().cast<Char>(),
|
||||
bufferPointer.ref,
|
||||
),
|
||||
);
|
||||
|
||||
calloc.free(bufferPointer);
|
||||
|
||||
final json = response.buf.toJson();
|
||||
if (response.command.cast<Utf8>().toDartString() == "error") {
|
||||
throw json;
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
Future<void> redactEvent(RedactEventRequest report) =>
|
||||
_sendCommand("redact_event", report.toJson());
|
||||
|
||||
Future<Event> sendMessage(SendMessageRequest request) async =>
|
||||
Event.fromJson(await _sendCommand("send_message", request.toJson()));
|
||||
|
||||
Future<Event> sendEvent(SendEventRequest request) async {
|
||||
final json = request.toJson();
|
||||
final content = request.content.toJson();
|
||||
|
||||
return Event.fromJson(
|
||||
await _sendCommand("send_event", {
|
||||
...json,
|
||||
"content": {
|
||||
...content,
|
||||
"m.relates_to": {
|
||||
...((content["m.relates_to"] as Map<String, dynamic>?) ?? {}),
|
||||
"event_id": request.relatesTo,
|
||||
"rel_type": request.relationType,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Future<String?> setState(SetStateRequest request) async =>
|
||||
await _sendCommand("set_state", request.toJson());
|
||||
|
||||
Future<String?> verify(String recoveryKey) async {
|
||||
try {
|
||||
await _sendCommand("verify", {"recovery_key": recoveryKey});
|
||||
return null;
|
||||
} catch (error) {
|
||||
return error.toString();
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> joinRoom(JoinRoomRequest request) async =>
|
||||
(await _sendCommand("join_room", request.toJson()))["room_id"];
|
||||
|
||||
Future<RoomSummary> getRoomSummary(JoinRoomRequest request) async =>
|
||||
.fromJson(await _sendCommand("get_room_summary", request.toJson()));
|
||||
|
||||
Future<void> leaveRoom(Room room) async {
|
||||
if (room.metadata == null) return;
|
||||
await _sendCommand("leave_room", {"room_id": room.metadata!.id});
|
||||
}
|
||||
|
||||
// (await _sendCommand("get_event_context", {
|
||||
// "room_id": request.roomId,
|
||||
// "event_id": r"$OqZT4NuTj0J1-771IOEEWRI4XdumRNu6ighlvO3K3gc",
|
||||
// }));
|
||||
|
||||
Future<IList<Event>> getRoomState(GetRoomStateRequest request) async {
|
||||
Future<List?> getState(GetRoomStateRequest request) async =>
|
||||
(await _sendCommand("get_room_state", request.toJson())) as List?;
|
||||
final response = await getState(request);
|
||||
|
||||
return .new(
|
||||
(response ?? await getState(request.copyWith(refetch: true)) ?? []).map(
|
||||
(event) => .fromJson(event),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<IList<Event>?> getRelatedEvents(
|
||||
GetRelatedEventsRequest request,
|
||||
) async {
|
||||
final response =
|
||||
(await _sendCommand("get_related_events", request.toJson())) as List?;
|
||||
return .new(response?.map((event) => .fromJson(event)));
|
||||
}
|
||||
|
||||
Future<Event?> getEvent(GetEventRequest request) async {
|
||||
final json = await _sendCommand("get_event", request.toJson());
|
||||
return json == null ? null : .fromJson(json);
|
||||
}
|
||||
|
||||
Future<OpenGraphData> getUrlPreview(Uri url) async =>
|
||||
.fromJson(await _sendCommand("get_url_preview", {"url": url.toString()}));
|
||||
|
||||
Future<Paginate> paginate(PaginateRequest request) async =>
|
||||
.fromJson(await _sendCommand("paginate", request.toJson()));
|
||||
|
||||
Future<ProfileResponse> getProfile(String userId) async =>
|
||||
.fromJson(await _sendCommand("get_profile", {"user_id": userId}));
|
||||
|
||||
Future<void> reportEvent(ReportRequest request) =>
|
||||
_sendCommand("report_event", request.toJson());
|
||||
|
||||
Future<void> setMembership(SetMembershipRequest request) =>
|
||||
_sendCommand("set_membership", request.toJson());
|
||||
|
||||
Future<void> setAccountData(SetAccountDataRequest request) =>
|
||||
_sendCommand("set_account_data", request.toJson());
|
||||
|
||||
Future<MessageContent> uploadMedia(UploadMediaRequest request) async =>
|
||||
.fromJson(await _sendCommand("upload_media", request.toJson()));
|
||||
|
||||
Future<File> downloadMedia(DownloadMediaRequest request) async =>
|
||||
.new((await _sendCommand("download_media", request.toJson()))["path"]);
|
||||
|
||||
Future<void> logout() => _sendCommand("logout");
|
||||
|
||||
Future<void> markRead(Room room) async {
|
||||
final eventRowId = room.timeline[room.timeline.keys.reduce(max)];
|
||||
final event = eventRowId == null ? null : room.events[eventRowId];
|
||||
if (event == null || room.metadata == null) return;
|
||||
|
||||
await _sendCommand("mark_read", {
|
||||
"room_id": room.metadata!.id,
|
||||
"receipt_type": "m.read",
|
||||
"event_id": event.eventId,
|
||||
});
|
||||
}
|
||||
|
||||
Future<String> registerClient(OAuthRegisterClientRequest request) async =>
|
||||
(await _sendCommand(
|
||||
"oauth_register_client",
|
||||
request.toJson(),
|
||||
))["client_id"];
|
||||
|
||||
Future<OAuthAuthCodeResponse> getAuthUrl(OAuthGetAuthUrl request) async =>
|
||||
.fromJson(
|
||||
await _sendCommand("oauth_get_authorization_url", request.toJson()),
|
||||
);
|
||||
|
||||
Future<void> exchangeToken(OAuthExchangeTokenRequest request) async =>
|
||||
await _sendCommand("oauth_exchange_token", request.toJson());
|
||||
|
||||
Future<SpecVersionsResponse> getSpecVersions() async =>
|
||||
.fromJson(await _sendCommand("get_versions"));
|
||||
|
||||
Future<Uri?> discoverHomeserver(Uri homeserver) async {
|
||||
try {
|
||||
final response = await _sendCommand("discover_homeserver", {
|
||||
"user_id": "@fake-user:${homeserver.authority}",
|
||||
});
|
||||
return Uri.parse(response["m.homeserver"]?["base_url"]);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider<ClientController, int>(
|
||||
ClientController.new,
|
||||
);
|
||||
}
|
||||
244
lib/controllers/client_controller.dart
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
import "dart:developer";
|
||||
import "dart:ffi";
|
||||
import "dart:isolate";
|
||||
import "package:collection/collection.dart";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:ffi/ffi.dart";
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:nexus/controllers/account_data_controller.dart";
|
||||
import "package:nexus/controllers/client_state_controller.dart";
|
||||
import "package:nexus/controllers/init_complete_controller.dart";
|
||||
import "package:nexus/controllers/rooms_controller.dart";
|
||||
import "package:nexus/controllers/space_edges_controller.dart";
|
||||
import "package:nexus/controllers/sync_status_controller.dart";
|
||||
import "package:nexus/controllers/top_level_spaces_controller.dart";
|
||||
import "package:nexus/helpers/extensions/gomuks_buffer.dart";
|
||||
import "package:nexus/models/client_state.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/paginate.dart";
|
||||
import "package:nexus/models/requests/get_event_request.dart";
|
||||
import "package:nexus/models/requests/get_related_events_request.dart";
|
||||
import "package:nexus/models/requests/get_room_state_request.dart";
|
||||
import "package:nexus/models/requests/join_room_request.dart";
|
||||
import "package:nexus/models/requests/login_request.dart";
|
||||
import "package:nexus/models/profile.dart";
|
||||
import "package:nexus/models/requests/paginate_request.dart";
|
||||
import "package:nexus/models/requests/redact_event_request.dart";
|
||||
import "package:nexus/models/requests/report_request.dart";
|
||||
import "package:nexus/models/requests/send_message_request.dart";
|
||||
import "package:nexus/models/room.dart";
|
||||
import "package:nexus/models/sync_data.dart";
|
||||
import "package:nexus/models/sync_status.dart";
|
||||
import "package:nexus/src/third_party/gomuks.g.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
|
||||
class ClientController extends AsyncNotifier<int> {
|
||||
@override
|
||||
Future<int> build() async {
|
||||
final handle = await Isolate.run(GomuksInit);
|
||||
|
||||
final callable =
|
||||
NativeCallable<
|
||||
Void Function(Pointer<Char>, Int64, GomuksOwnedBuffer)
|
||||
>.listener((
|
||||
Pointer<Char> command,
|
||||
int requestId,
|
||||
GomuksOwnedBuffer data,
|
||||
) {
|
||||
try {
|
||||
final muksEventType = command.cast<Utf8>().toDartString();
|
||||
debugPrint("Handling $muksEventType...");
|
||||
final decodedMuksEvent = data.toJson();
|
||||
|
||||
switch (muksEventType) {
|
||||
case "client_state":
|
||||
ref
|
||||
.watch(ClientStateController.provider.notifier)
|
||||
.set(ClientState.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "sync_status":
|
||||
ref
|
||||
.watch(SyncStatusController.provider.notifier)
|
||||
.set(SyncStatus.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "init_complete":
|
||||
ref.watch(InitCompleteController.provider.notifier).complete();
|
||||
break;
|
||||
case "sync_complete":
|
||||
final syncData = SyncData.fromJson(decodedMuksEvent);
|
||||
final roomProvider = RoomsController.provider;
|
||||
final accountDataProvider = AccountDataController.provider;
|
||||
|
||||
if (syncData.clearState) {
|
||||
ref.invalidate(roomProvider);
|
||||
ref.invalidate(accountDataProvider);
|
||||
}
|
||||
|
||||
ref
|
||||
.watch(roomProvider.notifier)
|
||||
.update(syncData.rooms, syncData.leftRooms);
|
||||
ref
|
||||
.watch(accountDataProvider.notifier)
|
||||
.update(syncData.accountData);
|
||||
|
||||
if (syncData.topLevelSpaces != null) {
|
||||
ref
|
||||
.watch(TopLevelSpacesController.provider.notifier)
|
||||
.set(syncData.topLevelSpaces!);
|
||||
}
|
||||
|
||||
if (syncData.spaceEdges != null) {
|
||||
ref
|
||||
.watch(SpaceEdgesController.provider.notifier)
|
||||
.set(syncData.spaceEdges!);
|
||||
}
|
||||
|
||||
// ref
|
||||
// .watch(SyncStatusController.provider.notifier)
|
||||
// .set(SyncStatus.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
default:
|
||||
debugPrint("Unhandled event: $muksEventType");
|
||||
}
|
||||
debugPrint("Finished handling $muksEventType...");
|
||||
} catch (error, stackTrace) {
|
||||
debugger();
|
||||
debugPrintStack(stackTrace: stackTrace, label: error.toString());
|
||||
}
|
||||
});
|
||||
|
||||
ref.onDispose(() => GomuksDestroy(handle));
|
||||
ref.onDispose(callable.close);
|
||||
|
||||
final errorCode = GomuksStart(handle, callable.nativeFunction);
|
||||
|
||||
if (errorCode == 0) return handle;
|
||||
throw Exception("GomuksStart returned error code $errorCode");
|
||||
}
|
||||
|
||||
Future<dynamic> _sendCommand(
|
||||
String command, [
|
||||
Map<String, dynamic> data = const {},
|
||||
]) async {
|
||||
final bufferPointer = data.toGomuksBufferPtr();
|
||||
final handle = await future;
|
||||
final response = await Isolate.run(
|
||||
() => GomuksSubmitCommand(
|
||||
handle,
|
||||
command.toNativeUtf8().cast<Char>(),
|
||||
bufferPointer.ref,
|
||||
),
|
||||
);
|
||||
|
||||
calloc.free(bufferPointer);
|
||||
|
||||
final json = response.buf.toJson();
|
||||
if (json is String) throw json;
|
||||
return json;
|
||||
}
|
||||
|
||||
Future<void> redactEvent(RedactEventRequest report) =>
|
||||
_sendCommand("redact_event", report.toJson());
|
||||
|
||||
Future<void> sendMessage(SendMessageRequest request) =>
|
||||
_sendCommand("send_message", request.toJson());
|
||||
|
||||
Future<bool> verify(String recoveryKey) async {
|
||||
try {
|
||||
await _sendCommand("verify", {"recovery_key": recoveryKey});
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> joinRoom(JoinRoomRequest request) async {
|
||||
final response = await _sendCommand("join_room", request.toJson());
|
||||
return response["room_id"];
|
||||
}
|
||||
|
||||
Future<String?> getAccessToken() async {
|
||||
final response = await _sendCommand("get_account_info", {});
|
||||
return response?["access_token"];
|
||||
}
|
||||
|
||||
Future<void> leaveRoom(Room room) async {
|
||||
if (room.metadata == null) return;
|
||||
await _sendCommand("leave_room", {"room_id": room.metadata!.id});
|
||||
}
|
||||
|
||||
// (await _sendCommand("get_event_context", {
|
||||
// "room_id": request.roomId,
|
||||
// "event_id": r"$OqZT4NuTj0J1-771IOEEWRI4XdumRNu6ighlvO3K3gc",
|
||||
// }));
|
||||
|
||||
Future<IList<Event>> getRoomState(GetRoomStateRequest request) async {
|
||||
final response =
|
||||
(await _sendCommand("get_room_state", request.toJson())) as List;
|
||||
return response.map((event) => Event.fromJson(event)).toIList();
|
||||
}
|
||||
|
||||
Future<IList<Event>?> getRelatedEvents(
|
||||
GetRelatedEventsRequest request,
|
||||
) async {
|
||||
final response =
|
||||
(await _sendCommand("get_related_events", request.toJson())) as List?;
|
||||
return response?.map((event) => Event.fromJson(event)).toIList();
|
||||
}
|
||||
|
||||
Future<Event?> getEvent(GetEventRequest request) async {
|
||||
final event = request.room.events.firstWhereOrNull(
|
||||
(event) => event.eventId == request.eventId,
|
||||
);
|
||||
if (event != null) return event;
|
||||
|
||||
final json = await _sendCommand("get_event", request.toJson());
|
||||
return json == null ? null : Event.fromJson(json);
|
||||
}
|
||||
|
||||
Future<Paginate> paginate(PaginateRequest request) async =>
|
||||
Paginate.fromJson(await _sendCommand("paginate", request.toJson()));
|
||||
|
||||
Future<Profile> getProfile(String userId) async =>
|
||||
Profile.fromJson(await _sendCommand("get_profile", {"user_id": userId}));
|
||||
|
||||
Future<void> reportEvent(ReportRequest report) =>
|
||||
_sendCommand("report_event", report.toJson());
|
||||
|
||||
Future<void> markRead(Room room) async {
|
||||
final event = room.events.firstWhereOrNull(
|
||||
(event) => event.rowId == room.timeline.last.eventRowId,
|
||||
);
|
||||
if (event == null || room.metadata == null) return;
|
||||
|
||||
await _sendCommand("mark_read", {
|
||||
"room_id": room.metadata!.id,
|
||||
"receipt_type": "m.read",
|
||||
"event_id": event.eventId,
|
||||
});
|
||||
}
|
||||
|
||||
Future<bool> login(LoginRequest login) async {
|
||||
try {
|
||||
await _sendCommand("login", login.toJson());
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> discoverHomeserver(Uri homeserver) async {
|
||||
try {
|
||||
final response = await _sendCommand("discover_homeserver", {
|
||||
"user_id": "@fakeuser:${homeserver.host}",
|
||||
});
|
||||
return response["m.homeserver"]?["base_url"];
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider<ClientController, int>(
|
||||
ClientController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
|
||||
class ClientIdController extends AsyncNotifier<String> {
|
||||
final Uri homeserver;
|
||||
ClientIdController(this.homeserver);
|
||||
|
||||
@override
|
||||
Future<String> build() => ref
|
||||
.watch(ClientController.provider.notifier)
|
||||
.registerClient(
|
||||
.new(
|
||||
clientName: "Nexus",
|
||||
applicationType: .native,
|
||||
grantTypes: .new([.authorizationCode, .refreshToken]),
|
||||
responseTypes: .new([.code]),
|
||||
logoUri: Uri.https(
|
||||
"nexus.federated.nexus",
|
||||
"raw/branch/main/assets/mobile.svg",
|
||||
),
|
||||
homeserverUrl: homeserver,
|
||||
clientUri: Uri.https("nexus.federated.nexus"),
|
||||
redirectUris: .new([
|
||||
.new(scheme: "nexus.federated.nexus", path: "/"),
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
||||
static final provider =
|
||||
AsyncNotifierProvider.family<ClientIdController, String, Uri>(
|
||||
ClientIdController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -5,7 +5,9 @@ class ClientStateController extends Notifier<ClientState?> {
|
|||
@override
|
||||
Null build() => null;
|
||||
|
||||
void set(ClientState newState) => state = newState;
|
||||
void set(ClientState newState) {
|
||||
state = newState;
|
||||
}
|
||||
|
||||
static final provider = NotifierProvider<ClientStateController, ClientState?>(
|
||||
ClientStateController.new,
|
||||
14
lib/controllers/cross_cache_controller.dart
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import "package:cross_cache/cross_cache.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
|
||||
class CrossCacheController extends Notifier<CrossCache> {
|
||||
static const String spaceKey = "space";
|
||||
static const String roomKey = "room";
|
||||
|
||||
@override
|
||||
CrossCache build() => CrossCache();
|
||||
|
||||
static final provider = NotifierProvider<CrossCacheController, CrossCache>(
|
||||
CrossCacheController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
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:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:http/http.dart";
|
||||
import "package:nexus/models/emoji.dart";
|
||||
|
||||
typedef EmojiTuple = (IMap<String, EmojiCategory>, IMap<String, List<String>>);
|
||||
|
||||
class EmojiController extends AsyncNotifier<EmojiTuple> {
|
||||
@override
|
||||
Future<EmojiTuple> build() async {
|
||||
final response = await get(
|
||||
.https("github.com", "github/gemoji/raw/refs/heads/master/db/emoji.json"),
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception("Failed to load emoji data");
|
||||
}
|
||||
|
||||
final data = json.decode(response.body);
|
||||
|
||||
final entries = (data as List)
|
||||
.cast<Map<String, dynamic>>()
|
||||
.map(Emoji.fromJson)
|
||||
.toIList();
|
||||
|
||||
final categoryMap = entries.fold<IMap<String, IList<String>>>(
|
||||
.new(),
|
||||
(acc, entry) => acc.update(
|
||||
entry.category,
|
||||
(list) => list.add(entry.emoji),
|
||||
ifAbsent: () => .new([entry.emoji]),
|
||||
),
|
||||
);
|
||||
|
||||
final keywordMap = entries.fold<IMap<String, IList<String>>>(
|
||||
.new(),
|
||||
(acc, entry) => acc.add(
|
||||
entry.emoji,
|
||||
.new([...entry.tags, ...entry.aliases, entry.description]),
|
||||
),
|
||||
);
|
||||
|
||||
final customCategories = IMap.fromEntries(
|
||||
categoryMap.entries.map(
|
||||
(entry) => MapEntry(
|
||||
entry.key,
|
||||
EmojiCategory(
|
||||
name: entry.key,
|
||||
icon: switch (entry.key) {
|
||||
"Smileys & Emotion" => Icons.emoji_emotions,
|
||||
"People & Body" => Icons.emoji_people,
|
||||
"Animals & Nature" => Icons.emoji_nature,
|
||||
"Food & Drink" => Icons.emoji_food_beverage,
|
||||
"Travel & Places" => Icons.travel_explore,
|
||||
"Activities" => Icons.sports_soccer,
|
||||
"Objects" => Icons.emoji_objects,
|
||||
"Symbols" => Icons.emoji_symbols,
|
||||
"Flags" => Icons.emoji_flags,
|
||||
_ => Icons.category,
|
||||
},
|
||||
emojis: entry.value.toList(growable: false),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final customKeywords = IMap(
|
||||
.fromEntries(
|
||||
keywordMap.entries.map(
|
||||
(e) => .new(e.key, e.value.toList(growable: false)),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return (customCategories, customKeywords);
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider<EmojiController, EmojiTuple>(
|
||||
EmojiController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
import "package:collection/collection.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
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);
|
||||
|
||||
@override
|
||||
Future<Event?> build() async {
|
||||
final room = ref.watch(
|
||||
RoomsController.provider.select((value) => value[request.roomId]),
|
||||
);
|
||||
final event = room?.events.values.firstWhereOrNull(
|
||||
(event) => event.eventId == request.eventId,
|
||||
);
|
||||
|
||||
return event ??
|
||||
await ref
|
||||
.watch(ClientController.provider.notifier)
|
||||
.getEvent(request)
|
||||
.onError((_, _) => null);
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider.family
|
||||
.autoDispose<EventController, Event?, GetEventRequest>(
|
||||
EventController.new,
|
||||
);
|
||||
}
|
||||