Skip to content
This repository has been archived by the owner on Sep 9, 2024. It is now read-only.

Commit

Permalink
backends: make init async, add glitch (#355)
Browse files Browse the repository at this point in the history
* add glitch-soc with post formatting & emoji reactions support.
* force adapter creation to be async
  • Loading branch information
erincandescent authored Apr 8, 2023
1 parent 0516205 commit a0b3269
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/kaiteki/lib/account_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class AccountManager extends ChangeNotifier {

_logger.v("Trying to recover a ${key.type!.displayName} account");

final adapter = key.type!.createAdapter(key.host);
final adapter = await key.type!.createAdapter(key.host);

try {
await adapter.applySecrets(clientSecret, accountSecret);
Expand Down
20 changes: 14 additions & 6 deletions src/kaiteki/lib/fediverse/api_type.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
import "package:kaiteki/fediverse/adapter.dart";
import "package:kaiteki/fediverse/api_theme.dart";
import "package:kaiteki/fediverse/backends/glitch/adapter.dart";
import "package:kaiteki/fediverse/backends/mastodon/adapter.dart";
import "package:kaiteki/fediverse/backends/misskey/adapter.dart";
import "package:kaiteki/fediverse/backends/pleroma/adapter.dart";
import "package:kaiteki/fediverse/backends/twitter/v1/adapter.dart";
import "package:kaiteki/fediverse/backends/twitter/v2/adapter.dart";

TwitterAdapter _instantiateTwitterV2(String _) => TwitterAdapter();
OldTwitterAdapter _instantiateTwitterV1(String _) => OldTwitterAdapter();
Future<TwitterAdapter> _instantiateTwitterV2(String _) async =>
TwitterAdapter();
Future<OldTwitterAdapter> _instantiateTwitterV1(String _) async =>
OldTwitterAdapter();

enum ApiType {
mastodon(
createAdapter: MastodonAdapter.new,
createAdapter: MastodonAdapter.create,
theme: mastodonTheme,
adapterType: MastodonAdapter,
),
glitch(
createAdapter: GlitchAdapter.create,
theme: mastodonTheme,
adapterType: GlitchAdapter,
),
pleroma(
createAdapter: PleromaAdapter.new,
createAdapter: PleromaAdapter.create,
theme: pleromaTheme,
adapterType: PleromaAdapter,
),
misskey(
createAdapter: MisskeyAdapter.new,
createAdapter: MisskeyAdapter.create,
theme: misskeyTheme,
adapterType: MisskeyAdapter,
),
Expand All @@ -39,7 +47,7 @@ enum ApiType {
);

final String? _displayName;
final BackendAdapter Function(String instance) createAdapter;
final Future<BackendAdapter> Function(String instance) createAdapter;
final ApiTheme theme;
final List<String>? hosts;
final Type adapterType;
Expand Down
78 changes: 78 additions & 0 deletions src/kaiteki/lib/fediverse/backends/glitch/adapter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import "package:fediverse_objects/mastodon.dart" as mastodon;
import "package:kaiteki/fediverse/backends/glitch/capabilities.dart";
import "package:kaiteki/fediverse/backends/glitch/client.dart";
import "package:kaiteki/fediverse/backends/mastodon/shared_adapter.dart";
import "package:kaiteki/fediverse/interfaces/reaction_support.dart";

import "../../model/emoji/emoji.dart";
import "../../model/instance.dart";
import "../../model/notification.dart";
import "../../model/post/post.dart";

class GlitchAdapter extends SharedMastodonAdapter<GlitchClient>
implements ReactionSupport {
@override
final String instance;
final mastodon.Instance instanceInfo;

static Future<GlitchAdapter> create(String instance) async {
final cli = GlitchClient(instance);
final instanceInfo = await cli.getInstance();
return GlitchAdapter.custom(instance, instanceInfo, cli);
}

GlitchAdapter.custom(this.instance, this.instanceInfo, super.client);

@override
GlitchCapabilities get capabilities {
final supportsReactions =
(instanceInfo.configuration?.reactions?.maxReactions ?? 0) != 0;

return GlitchCapabilities(supportsReactions);
}

@override
Future<Instance?> probeInstance() async {
if (!instanceInfo.version.contains("+glitch")) {
return null;
}

return toInstance(instanceInfo);
}

@override
Future<Instance> getInstance() async {
return toInstance(instanceInfo);
}

@override
Future<void> deleteAccount(String password) {
// TODO(Craftplacer): implement deleteAccount
throw UnimplementedError();
}

@override
Future<void> markAllNotificationsAsRead() async {
// HACK(Craftplacer): refetching latest notifcation will mark previously unfetched notifications as read as well
final latest = await client.getNotifications(limit: 1);
if (latest.isEmpty) return;
await client.setMarkerPosition(notifications: latest.first.id);
}

@override
Future<void> markNotificationAsRead(Notification notification) {
throw UnsupportedError(
"Mastodon does not support marking individual notifications as read",
);
}

@override
Future<void> addReaction(Post post, Emoji emoji) async {
await client.react(post.id, emoji.tag);
}

@override
Future<void> removeReaction(Post post, Emoji emoji) async {
await client.removeReaction(post.id, emoji.tag);
}
}
27 changes: 27 additions & 0 deletions src/kaiteki/lib/fediverse/backends/glitch/capabilities.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import "package:kaiteki/fediverse/backends/mastodon/capabilities.dart";
import "package:kaiteki/fediverse/interfaces/reaction_support.dart";
import "package:kaiteki/fediverse/model/formatting.dart";

class GlitchCapabilities extends MastodonCapabilities
implements ReactionSupportCapabilities {
final bool supportsReactions;

const GlitchCapabilities(this.supportsReactions);

// TODO(erincandescent): Take from
// api/v1/instance:configuration.statuses.supported_media_types
@override
Set<Formatting> get supportedFormattings {
return const {
Formatting.plainText,
Formatting.markdown,
};
}

@override
bool get supportsCustomEmojiReactions => supportsReactions;
@override
bool get supportsUnicodeEmojiReactions => supportsReactions;
@override
bool get supportsMultipleReactions => supportsReactions;
}
20 changes: 20 additions & 0 deletions src/kaiteki/lib/fediverse/backends/glitch/client.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import "package:kaiteki/fediverse/backends/mastodon/client.dart";
import "package:kaiteki/http/http.dart";

class GlitchClient extends MastodonClient {
GlitchClient(super.instance);

Future<void> react(String postId, String emoji) async {
await client.sendRequest(
HttpMethod.post,
"/api/v1/statuses/$postId/react/$emoji",
);
}

Future<void> removeReaction(String postId, String emoji) async {
await client.sendRequest(
HttpMethod.post,
"/api/v1/statuses/$postId/unreact/$emoji",
);
}
}
5 changes: 3 additions & 2 deletions src/kaiteki/lib/fediverse/backends/mastodon/adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class MastodonAdapter extends SharedMastodonAdapter<MastodonClient> {
@override
final String instance;

factory MastodonAdapter(String instance) {
static Future<MastodonAdapter> create(String instance) async {
return MastodonAdapter.custom(instance, MastodonClient(instance));
}

Expand All @@ -17,7 +17,8 @@ class MastodonAdapter extends SharedMastodonAdapter<MastodonClient> {
Future<Instance?> probeInstance() async {
final instance = await client.getInstance();

if (instance.version.contains("Pleroma")) {
if (instance.version.contains("Pleroma") ||
instance.version.contains("+glitch")) {
return null;
}

Expand Down
2 changes: 1 addition & 1 deletion src/kaiteki/lib/fediverse/backends/misskey/adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class MisskeyAdapter extends DecentralizedBackendAdapter
@override
final String instance;

factory MisskeyAdapter(String instance) {
static Future<MisskeyAdapter> create(String instance) async {
return MisskeyAdapter.custom(instance, MisskeyClient(instance));
}

Expand Down
9 changes: 2 additions & 7 deletions src/kaiteki/lib/fediverse/backends/pleroma/adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,8 @@ class PleromaAdapter //
@override
final String instance;

factory PleromaAdapter(String instance) {
return PleromaAdapter.custom(
instance,
PleromaClient(
instance,
),
);
static Future<PleromaAdapter> create(String instance) async {
return PleromaAdapter.custom(instance, PleromaClient(instance));
}

PleromaAdapter.custom(this.instance, super.client);
Expand Down
10 changes: 7 additions & 3 deletions src/kaiteki/lib/fediverse/instance_prober.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Future<InstanceProbeResult> probeInstance(
}

if (result.instance == null) {
final adapter = type.createAdapter(host);
final adapter = await type.createAdapter(host);
result = result.copyWith(instance: await adapter.getInstance());
}

Expand Down Expand Up @@ -147,7 +147,7 @@ Future<InstanceProbeResult?> _probeActivityPubNodeInfo(String host) async {
final nodeInfo = await fetchNodeInfo(host);
if (nodeInfo == null) return null;

final apiType = const <String, ApiType>{
var apiType = const <String, ApiType>{
"mastodon": ApiType.mastodon,
"pleroma": ApiType.pleroma,
"misskey": ApiType.misskey,
Expand All @@ -158,6 +158,10 @@ Future<InstanceProbeResult?> _probeActivityPubNodeInfo(String host) async {
}[nodeInfo.software.name];

if (apiType == null) return null;
if (apiType == ApiType.mastodon &&
nodeInfo.software.version.contains("+glitch")) {
apiType = ApiType.glitch;
}

return InstanceProbeResult.successful(
apiType,
Expand All @@ -169,7 +173,7 @@ Future<InstanceProbeResult?> _probeActivityPubNodeInfo(String host) async {
Future<InstanceProbeResult?> _probeEndpoints(String host) async {
for (final apiType in ApiType.values) {
try {
final adapter = apiType.createAdapter(host);
final adapter = await apiType.createAdapter(host);

if (adapter is! DecentralizedBackendAdapter) continue;

Expand Down
6 changes: 3 additions & 3 deletions src/kaiteki/lib/ui/auth/login/login_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class InstanceCompound {
@override
int get hashCode => host.hashCode ^ type.hashCode ^ data.hashCode;

BackendAdapter createAdapter() => type.createAdapter(host);
Future<BackendAdapter> createAdapter() => type.createAdapter(host);
}

class CallbackRequest<T, K extends Function> {
Expand Down Expand Up @@ -303,7 +303,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
if (selectedType == null) return null;
type = selectedType;

final adapter = type.createAdapter(host);
final adapter = await type.createAdapter(host);
instance = await adapter.getInstance();
}

Expand Down Expand Up @@ -369,7 +369,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {

Future<void> _login(InstanceCompound instance) async {
final accounts = ref.read(accountManagerProvider);
final adapter = instance.createAdapter();
final adapter = await instance.createAdapter();

final result = await adapter.login(
await accounts.getClientSecret(instance.host),
Expand Down
2 changes: 1 addition & 1 deletion src/kaiteki/lib/ui/user/user_screen_old.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class _UserScreenState extends ConsumerState<OldUserScreen>

// initialize client
final adapter =
asyncValue.type!.createAdapter(user.host);
await asyncValue.type!.createAdapter(user.host);

// override adapter being used with
// dependency injection
Expand Down

0 comments on commit a0b3269

Please sign in to comment.