oauth support is almost done
This commit is contained in:
parent
4a23939191
commit
52769238bd
19 changed files with 146 additions and 9 deletions
|
|
@ -22,6 +22,14 @@
|
|||
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"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class AuthUrlController extends AsyncNotifier<OAuthAuthCodeResponse> {
|
|||
.getAuthUrl(
|
||||
.new(
|
||||
homeserverUrl: homeserver,
|
||||
redirectUri: .new(scheme: "nexus.federated.nexus"),
|
||||
redirectUri: .new(scheme: "nexus.federated.nexus", path: "/"),
|
||||
responseMode: .query,
|
||||
scopes: .new([.clientApi]),
|
||||
clientId: await ref.watch(
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ 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.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";
|
||||
|
|
@ -288,6 +289,9 @@ class ClientController extends AsyncNotifier<int> {
|
|||
await _sendCommand("oauth_get_authorization_url", request.toJson()),
|
||||
);
|
||||
|
||||
Future<void> exchangeToken(OAuthExchangeTokenRequest request) async =>
|
||||
await _sendCommand("oauth_exchange_token", request.toJson());
|
||||
|
||||
Future<Uri?> discoverHomeserver(Uri homeserver) async {
|
||||
try {
|
||||
final response = await _sendCommand("discover_homeserver", {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ class ClientIdController extends AsyncNotifier<String> {
|
|||
),
|
||||
homeserverUrl: homeserver,
|
||||
clientUri: Uri.https("nexus.federated.nexus"),
|
||||
redirectUris: .new([.new(scheme: "nexus.federated.nexus")]),
|
||||
redirectUris: .new([
|
||||
.new(scheme: "nexus.federated.nexus", path: "/"),
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ void main() async {
|
|||
|
||||
runApp(
|
||||
ProviderScope(
|
||||
retry: null,
|
||||
observers: [
|
||||
// Change false to true if you want debug information on provider reloads
|
||||
// ignore: dead_code
|
||||
|
|
|
|||
17
lib/models/requests/oauth/exchange_token.dart
Normal file
17
lib/models/requests/oauth/exchange_token.dart
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import "package:freezed_annotation/freezed_annotation.dart";
|
||||
part "exchange_token.freezed.dart";
|
||||
part "exchange_token.g.dart";
|
||||
|
||||
@freezed
|
||||
abstract class OAuthExchangeTokenRequest with _$OAuthExchangeTokenRequest {
|
||||
const factory OAuthExchangeTokenRequest({
|
||||
required Uri homeserverUrl,
|
||||
required String codeVerifier,
|
||||
required Uri redirectUri,
|
||||
required String code,
|
||||
required String clientId,
|
||||
}) = _OAuthExchangeTokenRequest;
|
||||
|
||||
factory OAuthExchangeTokenRequest.fromJson(Map<String, Object?> json) =>
|
||||
_$OAuthExchangeTokenRequestFromJson(json);
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ class ChatPage extends ConsumerWidget {
|
|||
final showMembersByDefault = constraints.maxWidth > 1000;
|
||||
final initComplete = ref.watch(InitCompleteController.provider);
|
||||
final roomId = ref.watch(KeyController.provider(KeyController.roomKey));
|
||||
|
||||
ref.read(EmojiController.provider);
|
||||
|
||||
return Scaffold(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import "package:app_links/app_links.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
import "package:flutter_svg/flutter_svg.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:nexus/controllers/auth_url.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/controllers/client_id.dart";
|
||||
import "package:nexus/helpers/launch_helper.dart";
|
||||
import "package:nexus/main.dart";
|
||||
import "package:nexus/models/homeserver.dart";
|
||||
|
|
@ -48,11 +50,35 @@ class SelectServerPage extends HookConsumerWidget {
|
|||
),
|
||||
);
|
||||
} else {
|
||||
final authUrl = await ref.read(
|
||||
final codeResponse = await ref.watch(
|
||||
AuthUrlController.provider(newUrl).future,
|
||||
);
|
||||
|
||||
await ref.watch(LaunchHelper.provider).launchUrl(authUrl.url);
|
||||
await ref.watch(LaunchHelper.provider).launchUrl(codeResponse.url);
|
||||
|
||||
AppLinks().uriLinkStream.listen((encodedUri) async {
|
||||
final code = encodedUri.queryParameters["code"];
|
||||
|
||||
if (code != null) {
|
||||
await ref
|
||||
.watch(ClientController.provider.notifier)
|
||||
.exchangeToken(
|
||||
.new(
|
||||
homeserverUrl: newUrl,
|
||||
codeVerifier: codeResponse.codeVerifier,
|
||||
redirectUri: .new(
|
||||
scheme: "nexus.federated.nexus",
|
||||
path: "/",
|
||||
),
|
||||
code: code,
|
||||
clientId: await ref.watch(
|
||||
ClientIdController.provider(newUrl).future,
|
||||
),
|
||||
),
|
||||
)
|
||||
.onError(showError);
|
||||
}
|
||||
});
|
||||
// await Navigator.of(context).push(
|
||||
// MaterialPageRoute(builder: (_) => LoginPage(homeserver: newUrl)),
|
||||
// );
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <dynamic_color/dynamic_color_plugin.h>
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <gtk/gtk_plugin.h>
|
||||
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
||||
#include <media_kit_video/media_kit_video_plugin.h>
|
||||
#include <screen_retriever_linux/screen_retriever_linux_plugin.h>
|
||||
|
|
@ -21,6 +22,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) gtk_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin");
|
||||
gtk_plugin_register_with_registrar(gtk_registrar);
|
||||
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
|
||||
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
dynamic_color
|
||||
file_selector_linux
|
||||
gtk
|
||||
media_kit_libs_linux
|
||||
media_kit_video
|
||||
screen_retriever_linux
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@
|
|||
Name=Nexus
|
||||
GenericName=Matrix Client
|
||||
Comment=A simple and user-friendly Matrix client
|
||||
Exec=nexus
|
||||
Exec=nexus %u
|
||||
Icon=nexus
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Chat;Network;InstantMessaging;
|
||||
Categories=Chat;Network;InstantMessaging;
|
||||
MimeType=x-scheme-handler/nexus.federated.nexus;
|
||||
|
|
@ -23,6 +23,13 @@ static void first_frame_cb(MyApplication* self, FlView *view)
|
|||
// Implements GApplication::activate.
|
||||
static void my_application_activate(GApplication* application) {
|
||||
MyApplication* self = MY_APPLICATION(application);
|
||||
|
||||
GList* windows = gtk_application_get_windows(GTK_APPLICATION(application));
|
||||
if (windows) {
|
||||
gtk_window_present(GTK_WINDOW(windows->data));
|
||||
return;
|
||||
}
|
||||
|
||||
GtkWindow* window =
|
||||
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
|
||||
|
||||
|
|
@ -93,7 +100,7 @@ static gboolean my_application_local_command_line(GApplication* application, gch
|
|||
g_application_activate(application);
|
||||
*exit_status = 0;
|
||||
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Implements GApplication::startup.
|
||||
|
|
@ -140,6 +147,6 @@ MyApplication* my_application_new() {
|
|||
|
||||
return MY_APPLICATION(g_object_new(my_application_get_type(),
|
||||
"application-id", APPLICATION_ID,
|
||||
"flags", G_APPLICATION_NON_UNIQUE,
|
||||
"flags", G_APPLICATION_HANDLES_COMMAND_LINE | G_APPLICATION_HANDLES_OPEN,
|
||||
nullptr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import app_links
|
||||
import dynamic_color
|
||||
import file_picker
|
||||
import file_selector_macos
|
||||
|
|
@ -18,6 +19,7 @@ import wakelock_plus
|
|||
import window_manager
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
|
||||
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
|
||||
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
|
||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||
|
|
|
|||
|
|
@ -28,5 +28,18 @@
|
|||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<!-- abstract name for this URL type (you can leave it blank) -->
|
||||
<string>auth_callback</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<!-- your schemes -->
|
||||
<string>nexus.federated.nexus</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
40
pubspec.lock
40
pubspec.lock
|
|
@ -41,6 +41,38 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.11"
|
||||
app_links:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: app_links
|
||||
sha256: "3462d9defc61565fde4944858b59bec5be2b9d5b05f20aed190adb3ad08a7abc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
app_links_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_linux
|
||||
sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
app_links_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_platform_interface
|
||||
sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
app_links_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_web
|
||||
sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -558,6 +590,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
gtk:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: gtk
|
||||
sha256: "4ff85b2a16724029dd9e5bbb5a94b6918f9973f74ba571c949d2002801879cf5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
hooks:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ dependencies:
|
|||
m3e_card_list: ^0.1.0
|
||||
xdg_directories: ^1.1.0
|
||||
package_info_plus: ^9.0.1
|
||||
app_links: ^7.0.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: 2.15.0
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <app_links/app_links_plugin_c_api.h>
|
||||
#include <dynamic_color/dynamic_color_plugin_c_api.h>
|
||||
#include <file_selector_windows/file_selector_windows.h>
|
||||
#include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h>
|
||||
|
|
@ -15,6 +16,8 @@
|
|||
#include <window_manager/window_manager_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
AppLinksPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("AppLinksPluginCApi"));
|
||||
DynamicColorPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
|
||||
FileSelectorWindowsRegisterWithRegistrar(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
app_links
|
||||
dynamic_color
|
||||
file_selector_windows
|
||||
media_kit_libs_windows_video
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
#include <flutter/dart_project.h>
|
||||
#include <flutter/flutter_view_controller.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "app_links/app_links_plugin_c_api.h"
|
||||
#include "flutter_window.h"
|
||||
#include "utils.h"
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
_In_ wchar_t *command_line, _In_ int show_command) {
|
||||
// Forward the link to an existing instance, if any, then exit.
|
||||
// You may ignore the result if you need to create another window.
|
||||
if (SendAppLinkToInstance()) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
// Attach to console when present (e.g., 'flutter run') or create a
|
||||
// new console when running with a debugger.
|
||||
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue