Files
tatuchat/lib/config/miniapp_config.dart
Welton Moura 1f692b1e4e
Some checks failed
Main Deploy Workflow / deploy_web (push) Has been cancelled
Main Deploy Workflow / deploy_playstore_internal (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
feat: mini apps customizados com importacao por arquivo/URL, paleta de cores, avatar autenticado e documentacao
2026-09-18 15:11:12 -03:00

127 lines
4.0 KiB
Dart

// SPDX-FileCopyrightText: 2019-Present Christian Kußowski
// SPDX-FileCopyrightText: 2019-Present Contributors to FluffyChat
//
// SPDX-License-Identifier: AGPL-3.0-or-later
import 'package:material_ui/material_ui.dart';
import 'package:matrix/matrix.dart';
import 'package:tatchat/l10n/l10n.dart';
import 'package:tatchat/utils/miniapp_store.dart';
/// ID of the built-in tasks example app.
const String miniAppTasksId = 'tasks';
/// ID of the built-in account data explorer app.
const String miniAppAccountDataId = 'accountdata';
/// Static registry of all built-in mini apps that ship with this build. A mini
/// app only shows up in the "Apps" page once the user installs it (see
/// [installedMiniApps]). Additionally to this list, users can import their own
/// single-file HTML apps which are resolved through [resolveMiniAppConfig].
const List<MiniAppConfig> availableMiniApps = [
MiniAppConfig(
id: miniAppTasksId,
icon: Icons.checklist_rounded,
color: Color(0xFF00D084),
htmlAsset: 'assets/miniapps/tasks.html',
),
MiniAppConfig(
id: miniAppAccountDataId,
icon: Icons.storage_rounded,
color: Color(0xFF1F8EF1),
htmlAsset: 'assets/miniapps/accountdata.html',
),
];
/// Declarative description of a mini app. The rendering is either a
/// self-contained HTML document loaded from [htmlAsset] (built-in apps) or
/// from [html] which is stored in the user's account data (imported apps).
class MiniAppConfig {
final String id;
final IconData icon;
final Color color;
final String? name;
final String? htmlAsset;
final String? html;
const MiniAppConfig({
required this.id,
required this.icon,
required this.color,
this.name,
this.htmlAsset,
this.html,
});
/// Config for a user-imported app whose HTML source is persisted in the
/// account data store.
MiniAppConfig.custom({
required String id,
String? name,
String? html,
}) : this(
id: id,
icon: Icons.web_asset_rounded,
color: const Color(0xFF9C27B0),
name: name,
html: html,
);
bool get isCustom => html != null || htmlAsset == null;
/// Resolves the HTML source that should be rendered for this app. Returns a
/// bundled asset path for built-in apps or the raw HTML for imported apps.
String? get htmlSource => html ?? htmlAsset;
}
/// Resolves the config of a single installed app, whether it is built-in or
/// user-imported. Returns null if the app is not installed or not available.
MiniAppConfig? resolveMiniAppConfig(Client client, String appId) {
for (final app in availableMiniApps) {
if (app.id == appId) return app;
}
if (client.isMiniAppInstalled(appId)) {
final html = client.getMiniAppSource(appId);
if (html != null) {
return MiniAppConfig.custom(
id: appId,
name: client.getMiniAppName(appId),
html: html,
);
}
}
return null;
}
/// Returns the configs of all installed apps: built-in ones plus the
/// user-imported ones. The visual order is: installed built-in apps first,
/// then imported apps.
List<MiniAppConfig> installedMiniAppConfigs(Client client) {
final installed = client.installedMiniApps;
return [
for (final app in availableMiniApps)
if (installed.contains(app.id)) app,
for (final id in installed)
if (!availableMiniApps.any((app) => app.id == id))
if (client.getMiniAppSource(id) != null)
MiniAppConfig.custom(
id: id,
name: client.getMiniAppName(id),
html: client.getMiniAppSource(id),
),
];
}
/// Resolves the localized display name of a mini app configuration.
String miniAppName(BuildContext context, MiniAppConfig app) {
final customName = app.name;
if (customName != null && customName.isNotEmpty) return customName;
switch (app.id) {
case miniAppTasksId:
return L10n.of(context).tasks;
case miniAppAccountDataId:
return L10n.of(context).accountDataEditor;
default:
return app.id;
}
}