Enable Desktop support

This commit is contained in:
Christian Pauly 2020-04-26 08:24:41 +02:00
parent be948ff8b1
commit f51123150d
28 changed files with 463 additions and 78 deletions

View File

@ -3,7 +3,6 @@ import 'package:fluffychat/utils/string_color.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_advanced_networkimage/provider.dart';
import 'matrix.dart';
class Avatar extends StatelessWidget {
@ -42,7 +41,7 @@ class Avatar extends StatelessWidget {
backgroundImage: mxContent.mxc?.isNotEmpty ?? false
? AdvancedNetworkImage(
src,
useDiskCache: !kIsWeb,
useDiskCache: Matrix.of(context).client.storeAPI.extended,
)
: null,
backgroundColor: mxContent.mxc.isEmpty

View File

@ -6,7 +6,7 @@ import 'package:fluffychat/utils/app_route.dart';
import 'package:fluffychat/views/chat_details.dart';
import 'package:fluffychat/views/chat_list.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:fluffychat/utils/cross_url_launcher.dart';
import 'dialogs/simple_dialogs.dart';
import 'matrix.dart';

View File

@ -53,7 +53,8 @@ class ContentBanner extends StatelessWidget {
fit: BoxFit.cover,
image: AdvancedNetworkImage(
src,
useDiskCache: !kIsWeb,
useDiskCache:
Matrix.of(context).client.storeAPI.extended,
),
)
: Icon(defaultIcon, size: 300)

View File

@ -55,9 +55,9 @@ class _ImageBubbleState extends State<ImageBubble> {
);
}
_getFile().then((MatrixFile file) {
setState(() => _file = file);
if (mounted) setState(() => _file = file);
}, onError: (error) {
setState(() => _error = error);
if (mounted) setState(() => _error = error);
});
return Center(
child: CircularProgressIndicator(),

View File

@ -9,9 +9,9 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
import 'package:localstorage/localstorage.dart';
import 'package:cross_local_storage/cross_local_storage.dart';
import 'package:path_provider/path_provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:fluffychat/utils/cross_url_launcher.dart';
import '../i18n/i18n.dart';
import '../utils/app_route.dart';
@ -25,6 +25,8 @@ import 'avatar.dart';
class Matrix extends StatefulWidget {
static const String callNamespace = 'chat.fluffy.jitsi_call';
static const String defaultHomeserver = 'tchncs.de';
static bool get isMobile =>
kIsWeb ? false : (Platform.isAndroid || Platform.isIOS);
final Widget child;
@ -70,11 +72,10 @@ class MatrixState extends State<Matrix> {
String jitsiInstance = 'https://meet.jit.si/';
void clean() async {
if (!kIsWeb) return;
if (Matrix.isMobile) return;
final LocalStorage storage = LocalStorage('LocalStorage');
await storage.ready;
await storage.deleteItem(widget.clientName);
final LocalStorageInterface storage = await LocalStorage.getInstance();
await storage.remove(widget.clientName);
}
BuildContext _loadingDialogContext;
@ -325,10 +326,10 @@ class MatrixState extends State<Matrix> {
void _initWithStore() async {
Future<LoginState> initLoginState = client.onLoginStateChanged.stream.first;
client.storeAPI = kIsWeb ? Store(client) : ExtendedStore(client);
client.storeAPI = !Matrix.isMobile ? Store(client) : ExtendedStore(client);
debugPrint(
"[Store] Store is extended: ${client.storeAPI.extended.toString()}");
if (await initLoginState == LoginState.logged && !kIsWeb) {
if (await initLoginState == LoginState.logged && Matrix.isMobile) {
await setupFirebase();
}
}
@ -406,7 +407,7 @@ class MatrixState extends State<Matrix> {
void initState() {
if (widget.client == null) {
debugPrint("[Matrix] Init matrix client");
client = Client(widget.clientName, debug: true);
client = Client(widget.clientName, debug: false);
onJitsiCallSub ??= client.onEvent.stream
.where((e) =>
e.type == 'timeline' &&

View File

@ -7,7 +7,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
import 'package:link_text/link_text.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:fluffychat/utils/cross_url_launcher.dart';
import 'package:fluffychat/utils/matrix_file_extension.dart';
import 'matrix.dart';

View File

@ -34,6 +34,7 @@ class App extends StatelessWidget {
child: MaterialApp(
title: 'FluffyChat',
theme: ThemeSwitcherWidget.of(context).themeData,
debugShowCheckedModeBanner: kIsWeb || Matrix.isMobile,
localizationsDelegates: [
AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,

View File

@ -0,0 +1,18 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
import 'package:url_launcher/url_launcher.dart' as native_launcher;
import 'package:system/system.dart';
void launch(String url) {
if (kIsWeb || Platform.isAndroid || Platform.isIOS) {
native_launcher.launch(url);
} else if (Platform.isLinux) {
System.invoke('xdg-open $url');
} else if (Platform.isMacOS) {
System.invoke('open $url');
} else {
showToast('Open urls is not yet supported on this platform.');
}
}

View File

@ -1,10 +1,11 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:localstorage/localstorage.dart';
import 'package:cross_local_storage/cross_local_storage.dart';
import 'dart:async';
import 'dart:core';
import 'package:path/path.dart' as p;
@ -12,20 +13,23 @@ import 'package:sqflite/sqflite.dart';
class Store extends StoreAPI {
final Client client;
final LocalStorage storage;
Future<LocalStorageInterface> storageFuture;
LocalStorageInterface storage;
final FlutterSecureStorage secureStorage;
Store(this.client)
: storage = LocalStorage('LocalStorage'),
secureStorage = kIsWeb ? null : FlutterSecureStorage() {
: storageFuture = LocalStorage.getInstance(),
secureStorage = !(Platform.isIOS || Platform.isAndroid)
? null
: FlutterSecureStorage() {
_init();
}
Future<dynamic> getItem(String key) async {
if (kIsWeb) {
await storage.ready;
if (!(Platform.isIOS || Platform.isAndroid)) {
storage = await storageFuture;
try {
return await storage.getItem(key);
return await storage.get(key);
} catch (_) {
return null;
}
@ -38,9 +42,9 @@ class Store extends StoreAPI {
}
Future<void> setItem(String key, String value) async {
if (kIsWeb) {
await storage.ready;
return await storage.setItem(key, value);
if (!(Platform.isIOS || Platform.isAndroid)) {
storage = await storageFuture;
return await storage.setString(key, value);
}
if (value == null) {
return await secureStorage.delete(key: key);
@ -89,7 +93,7 @@ class Store extends StoreAPI {
newMatrixVersions: List<String>.from(credentials["matrixVersions"] ?? []),
newToken: credentials["token"],
newUserID: credentials["userID"],
newPrevBatch: kIsWeb
newPrevBatch: !(Platform.isIOS || Platform.isAndroid)
? null
: (credentials["prev_batch"]?.isEmpty ?? true)
? null
@ -112,7 +116,9 @@ class Store extends StoreAPI {
return;
}
Future<void> clear() => kIsWeb ? storage.clear() : secureStorage.deleteAll();
Future<void> clear() => !(Platform.isIOS || Platform.isAndroid)
? storage.clear()
: secureStorage.deleteAll();
}
/// Responsible to store all data persistent and to query objects from the

View File

@ -1,17 +1,16 @@
import 'dart:io';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/components/matrix.dart';
import 'package:flutter/foundation.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import 'package:system/system.dart';
import 'package:universal_html/prefer_universal/html.dart' as html;
import 'package:mime_type/mime_type.dart';
extension MatrixFileExtension on MatrixFile {
void open() async {
Directory tempDir = await getTemporaryDirectory();
final file = File(tempDir.path + "/" + path.split("/").last);
file.writeAsBytesSync(bytes);
if (kIsWeb) {
final fileName = path.split('/').last;
final mimeType = mime(fileName);
@ -26,8 +25,16 @@ extension MatrixFileExtension on MatrixFile {
html.document.body.append(element);
element.click();
element.remove();
} else {
} else if (Matrix.isMobile) {
Directory tempDir = await getTemporaryDirectory();
final file = File(tempDir.path + "/" + path.split("/").last);
file.writeAsBytesSync(bytes);
await OpenFile.open(file.path);
} else if (Platform.isLinux) {
final filePath = "/home/krille/Downloads/";
final file = File(filePath + path.split("/").last);
file.writeAsBytesSync(bytes);
System.invoke('xdg-open $filePath');
}
return;
}

View File

@ -3,7 +3,7 @@ import 'package:fluffychat/components/matrix.dart';
import 'package:fluffychat/utils/app_route.dart';
import 'package:fluffychat/views/chat.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:fluffychat/utils/cross_url_launcher.dart';
class UrlLauncher {
final String url;

View File

@ -2,7 +2,7 @@ import 'package:fluffychat/components/matrix.dart';
import 'package:fluffychat/i18n/i18n.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:fluffychat/utils/cross_url_launcher.dart';
import 'package:webview_flutter/webview_flutter.dart';
class AuthWebView extends StatelessWidget {

View File

@ -176,10 +176,6 @@ class _ChatState extends State<_Chat> {
}
void sendFileAction(BuildContext context) async {
if (kIsWeb) {
showToast(I18n.of(context).notSupportedInWeb);
return;
}
File file = await FilePicker.getFile();
if (file == null) return;
await matrix.tryRequestWithLoadingDialog(
@ -190,10 +186,6 @@ class _ChatState extends State<_Chat> {
}
void sendImageAction(BuildContext context) async {
if (kIsWeb) {
showToast(I18n.of(context).notSupportedInWeb);
return;
}
File file = await ImagePicker.pickImage(
source: ImageSource.gallery,
imageQuality: 50,
@ -208,10 +200,6 @@ class _ChatState extends State<_Chat> {
}
void openCameraAction(BuildContext context) async {
if (kIsWeb) {
showToast(I18n.of(context).notSupportedInWeb);
return;
}
File file = await ImagePicker.pickImage(
source: ImageSource.camera,
imageQuality: 50,
@ -590,7 +578,7 @@ class _ChatState extends State<_Chat> {
: Container(),
]
: <Widget>[
if (!kIsWeb && inputText.isEmpty)
if (Matrix.isMobile && inputText.isEmpty)
PopupMenuButton<String>(
icon: Icon(Icons.add),
onSelected: (String choice) async {
@ -669,8 +657,8 @@ class _ChatState extends State<_Chat> {
vertical: 4.0),
child: TextField(
minLines: 1,
maxLines: kIsWeb ? 1 : 8,
keyboardType: kIsWeb
maxLines: !Matrix.isMobile ? 1 : 8,
keyboardType: !Matrix.isMobile
? TextInputType.text
: TextInputType.multiline,
onSubmitted: (String text) {
@ -709,13 +697,13 @@ class _ChatState extends State<_Chat> {
),
),
),
if (!kIsWeb && inputText.isEmpty)
if (Matrix.isMobile && inputText.isEmpty)
IconButton(
icon: Icon(Icons.mic),
onPressed: () =>
voiceMessageAction(context),
),
if (kIsWeb || inputText.isNotEmpty)
if (!Matrix.isMobile || inputText.isNotEmpty)
IconButton(
icon: Icon(Icons.send),
onPressed: () => send(),

View File

@ -143,7 +143,7 @@ class _ChatListState extends State<ChatList> {
}
void _initReceiveSharingINtent() {
if (kIsWeb) return;
if (!Matrix.isMobile) return;
// For sharing images coming from outside the app while the app is in the memory
_intentFileStreamSubscription = ReceiveSharingIntent.getMediaStream()

View File

@ -7,7 +7,7 @@ import 'package:fluffychat/views/settings_devices.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:fluffychat/utils/cross_url_launcher.dart';
import 'app_info.dart';
import 'chat_list.dart';

1
linux/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
flutter/ephemeral

146
linux/Makefile Normal file
View File

@ -0,0 +1,146 @@
include app_configuration.mk
# Default build type.
BUILD=debug
FLUTTER_MANAGED_DIR=flutter
FLUTTER_EPHEMERAL_DIR=$(FLUTTER_MANAGED_DIR)/ephemeral
# Configuration provided via flutter tool.
FLUTTER_CONFIG_FILE=$(FLUTTER_EPHEMERAL_DIR)/generated_config.mk
include $(FLUTTER_CONFIG_FILE)
# Dependency locations
FLUTTER_APP_DIR=$(CURDIR)/..
FLUTTER_APP_BUILD_DIR=$(FLUTTER_APP_DIR)/build
OUT_DIR=$(FLUTTER_APP_BUILD_DIR)/linux
OBJ_DIR=$(OUT_DIR)/obj/$(BUILD)
# Libraries
FLUTTER_LIB_NAME=flutter_linux_glfw
FLUTTER_LIB=$(FLUTTER_EPHEMERAL_DIR)/lib$(FLUTTER_LIB_NAME).so
# Tools
FLUTTER_BIN=$(FLUTTER_ROOT)/bin/flutter
LINUX_BUILD=$(FLUTTER_ROOT)/packages/flutter_tools/bin/tool_backend.sh
# Resources
ICU_DATA_NAME=icudtl.dat
ICU_DATA_SOURCE=$(FLUTTER_EPHEMERAL_DIR)/$(ICU_DATA_NAME)
FLUTTER_ASSETS_NAME=flutter_assets
FLUTTER_ASSETS_SOURCE=$(FLUTTER_APP_BUILD_DIR)/$(FLUTTER_ASSETS_NAME)
# Bundle structure
BUNDLE_OUT_DIR=$(OUT_DIR)/$(BUILD)
BUNDLE_DATA_DIR=$(BUNDLE_OUT_DIR)/data
BUNDLE_LIB_DIR=$(BUNDLE_OUT_DIR)/lib
BIN_OUT=$(BUNDLE_OUT_DIR)/$(BINARY_NAME)
ICU_DATA_OUT=$(BUNDLE_DATA_DIR)/$(ICU_DATA_NAME)
FLUTTER_LIB_OUT=$(BUNDLE_LIB_DIR)/$(notdir $(FLUTTER_LIB))
ALL_LIBS_OUT=$(FLUTTER_LIB_OUT) \
$(foreach lib,$(EXTRA_BUNDLED_LIBRARIES),$(BUNDLE_LIB_DIR)/$(notdir $(lib)))
# Add relevant code from the wrapper library, which is intended to be statically
# built into the client.
# Use abspath for the wrapper root, which can contain relative paths; the
# intermediate build files will be based on the source path, which will cause
# issues if they start with one or more '../'s.
WRAPPER_ROOT=$(abspath $(FLUTTER_EPHEMERAL_DIR)/cpp_client_wrapper_glfw)
WRAPPER_SOURCES= \
$(WRAPPER_ROOT)/flutter_window_controller.cc \
$(WRAPPER_ROOT)/plugin_registrar.cc \
$(WRAPPER_ROOT)/engine_method_result.cc
# Use abspath for extra sources, which may also contain relative paths (see
# note above about WRAPPER_ROOT).
SOURCES=main.cc window_configuration.cc \
flutter/generated_plugin_registrant.cc \
$(WRAPPER_SOURCES) $(abspath $(EXTRA_SOURCES))
# Headers
WRAPPER_INCLUDE_DIR=$(WRAPPER_ROOT)/include
INCLUDE_DIRS=$(FLUTTER_EPHEMERAL_DIR) $(WRAPPER_INCLUDE_DIR)
# Build settings
ifneq ($(strip $(SYSTEM_LIBRARIES)),)
EXTRA_CPPFLAGS+=$(patsubst -I%,-isystem%,$(shell pkg-config --cflags $(SYSTEM_LIBRARIES)))
EXTRA_LDFLAGS+=$(shell pkg-config --libs $(SYSTEM_LIBRARIES))
endif
CXX=clang++
CPPFLAGS.release=-DNDEBUG
CPPFLAGS.profile=$(CPPFLAGS.release)
CXXFLAGS.release=-O2
CXXFLAGS.profile=$(CXXFLAGS.release)
CXXFLAGS=-std=c++14 -Wall -Werror $(CXXFLAGS.$(BUILD)) $(EXTRA_CXXFLAGS)
CPPFLAGS=$(patsubst %,-I%,$(INCLUDE_DIRS)) \
$(CPPFLAGS.$(BUILD)) $(EXTRA_CPPFLAGS)
LDFLAGS=-L$(BUNDLE_LIB_DIR) \
-l$(FLUTTER_LIB_NAME) \
$(EXTRA_LDFLAGS) \
-Wl,-rpath=\$$ORIGIN/lib
# Intermediate files.
OBJ_FILES=$(SOURCES:%.cc=$(OBJ_DIR)/%.o)
DEPENDENCY_FILES=$(OBJ_FILES:%.o=%.d)
# Targets
.PHONY: all
all: $(BIN_OUT) bundle
# Add the plugin targets, and their associated settings.
include $(FLUTTER_MANAGED_DIR)/generated_plugins.mk
EXTRA_BUNDLED_LIBRARIES+=$(PLUGIN_LIBRARIES)
EXTRA_LDFLAGS+=$(PLUGIN_LDFLAGS)
EXTRA_CPPFLAGS+=$(PLUGIN_CPPFLAGS)
# This is a phony target because the flutter tool cannot describe
# its inputs and outputs yet.
.PHONY: sync
sync: $(FLUTTER_CONFIG_FILE)
$(LINUX_BUILD) linux-x64 $(BUILD)
.PHONY: bundle
bundle: $(ICU_DATA_OUT) $(ALL_LIBS_OUT) bundleflutterassets
$(BIN_OUT): $(OBJ_FILES) $(ALL_LIBS_OUT)
mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OBJ_FILES) $(LDFLAGS) -o $@
$(WRAPPER_SOURCES) $(FLUTTER_LIB) $(ICU_DATA_SOURCE) $(FLUTTER_ASSETS_SOURCE) \
$(PLUGIN_TARGETS): | sync
# Plugin library bundling pattern.
$(BUNDLE_LIB_DIR)/%: $(OUT_DIR)/%
mkdir -p $(BUNDLE_LIB_DIR)
cp $< $@
$(FLUTTER_LIB_OUT): $(FLUTTER_LIB)
mkdir -p $(@D)
cp $< $@
$(ICU_DATA_OUT): $(ICU_DATA_SOURCE)
mkdir -p $(@D)
cp $< $@
-include $(DEPENDENCY_FILES)
$(OBJ_DIR)/%.o : %.cc | sync
mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -c $< -o $@
# Fully re-copy the assets directory on each build to avoid having to keep a
# comprehensive list of all asset files here, which would be fragile to changes
# in other files (e.g., adding a new font to pubspec.yaml).
.PHONY: bundleflutterassets
bundleflutterassets: $(FLUTTER_ASSETS_SOURCE)
mkdir -p $(BUNDLE_DATA_DIR)
rsync -rpu --delete $(FLUTTER_ASSETS_SOURCE) $(BUNDLE_DATA_DIR)
.PHONY: clean
clean:
rm -rf $(OUT_DIR); \
cd $(FLUTTER_APP_DIR); \
$(FLUTTER_BIN) clean

View File

@ -0,0 +1,16 @@
# This file contains variables that applications are likely to need to
# change, to isolate them from the main Makefile where the build rules are still
# in flux. This should simplify re-creating the runner while preserving local
# changes.
# Executable name.
BINARY_NAME=testbed
# Any extra source files to build.
EXTRA_SOURCES=
# Paths of any additional libraries to be bundled in the output directory.
EXTRA_BUNDLED_LIBRARIES=
# Extra flags (e.g., for library dependencies).
SYSTEM_LIBRARIES=gtk+-3.0 x11
EXTRA_CXXFLAGS=
EXTRA_CPPFLAGS=
EXTRA_LDFLAGS=

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,9 @@
//
// Generated file. Do not edit.
//
#include "generated_plugin_registrant.h"
void RegisterPlugins(flutter::PluginRegistry* registry) {
}

View File

@ -0,0 +1,13 @@
//
// Generated file. Do not edit.
//
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter/plugin_registry.h>
// Registers Flutter plugins.
void RegisterPlugins(flutter::PluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_

View File

@ -0,0 +1,25 @@
# Plugins to include in the build.
GENERATED_PLUGINS=\
GENERATED_PLUGINS_DIR=flutter/ephemeral/.plugin_symlinks
# A plugin library name plugin name with _plugin appended.
GENERATED_PLUGIN_LIB_NAMES=$(foreach plugin,$(GENERATED_PLUGINS),$(plugin)_plugin)
# Variables for use in the enclosing Makefile. Changes to these names are
# breaking changes.
PLUGIN_TARGETS=$(GENERATED_PLUGINS)
PLUGIN_LIBRARIES=$(foreach plugin,$(GENERATED_PLUGIN_LIB_NAMES),\
$(OUT_DIR)/lib$(plugin).so)
PLUGIN_LDFLAGS=$(patsubst %,-l%,$(GENERATED_PLUGIN_LIB_NAMES))
PLUGIN_CPPFLAGS=$(foreach plugin,$(GENERATED_PLUGINS),\
-I$(GENERATED_PLUGINS_DIR)/$(plugin)/linux)
# Targets
# Implicit rules don't match phony targets, so list plugin builds explicitly.
.PHONY: $(GENERATED_PLUGINS)
$(GENERATED_PLUGINS):
make -C $(GENERATED_PLUGINS_DIR)/$@/linux \
OUT_DIR=$(OUT_DIR) \
FLUTTER_EPHEMERAL_DIR="$(abspath flutter/ephemeral)"

82
linux/main.cc Normal file
View File

@ -0,0 +1,82 @@
#include <flutter/flutter_window_controller.h>
#include <linux/limits.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <vector>
// For plugin-compatible event handling (e.g., modal windows).
#include <X11/Xlib.h>
#include <gtk/gtk.h>
#include "flutter/generated_plugin_registrant.h"
#include "window_configuration.h"
namespace {
// Returns the path of the directory containing this executable, or an empty
// string if the directory cannot be found.
std::string GetExecutableDirectory() {
char buffer[PATH_MAX + 1];
ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer));
if (length > PATH_MAX) {
std::cerr << "Couldn't locate executable" << std::endl;
return "";
}
std::string executable_path(buffer, length);
size_t last_separator_position = executable_path.find_last_of('/');
if (last_separator_position == std::string::npos) {
std::cerr << "Unabled to find parent directory of " << executable_path
<< std::endl;
return "";
}
return executable_path.substr(0, last_separator_position);
}
} // namespace
int main(int argc, char **argv) {
// Resources are located relative to the executable.
std::string base_directory = GetExecutableDirectory();
if (base_directory.empty()) {
base_directory = ".";
}
std::string data_directory = base_directory + "/data";
std::string assets_path = data_directory + "/flutter_assets";
std::string icu_data_path = data_directory + "/icudtl.dat";
// Arguments for the Flutter Engine.
std::vector<std::string> arguments;
#ifdef NDEBUG
arguments.push_back("--disable-dart-asserts");
#endif
flutter::FlutterWindowController flutter_controller(icu_data_path);
flutter::WindowProperties window_properties = {};
window_properties.title = kFlutterWindowTitle;
window_properties.width = kFlutterWindowWidth;
window_properties.height = kFlutterWindowHeight;
// Start the engine.
if (!flutter_controller.CreateWindow(window_properties, assets_path,
arguments)) {
return EXIT_FAILURE;
}
RegisterPlugins(&flutter_controller);
// Set up for GTK event handling, needed by the GTK-based plugins.
gtk_init(0, nullptr);
XInitThreads();
// Run until the window is closed, processing GTK events in parallel for
// plugin handling.
while (flutter_controller.RunEventLoopWithTimeout(
std::chrono::milliseconds(10))) {
if (gtk_events_pending()) {
gtk_main_iteration();
}
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,5 @@
#include "window_configuration.h"
const char *kFlutterWindowTitle = "testbed";
const unsigned int kFlutterWindowWidth = 800;
const unsigned int kFlutterWindowHeight = 600;

View File

@ -0,0 +1,15 @@
#ifndef WINDOW_CONFIGURATION_
#define WINDOW_CONFIGURATION_
// This is a temporary approach to isolate common customizations from main.cpp,
// where the APIs are still in flux. This should simplify re-creating the
// runner while preserving local changes.
//
// Longer term there should be simpler configuration options for common
// customizations like this, without requiring native code changes.
extern const char *kFlutterWindowTitle;
extern const unsigned int kFlutterWindowWidth;
extern const unsigned int kFlutterWindowHeight;
#endif // WINDOW_CONFIGURATION_

1
preferences.json Normal file
View File

@ -0,0 +1 @@
{"theme":"light","amoled_enabled":"false","FluffyChat linux":"{\"deviceID\":\"FWTWDQTSXK\",\"deviceName\":\"FluffyChat linux\",\"homeserver\":\"https://ubports.chat\",\"matrixVersions\":[\"r0.0.1\",\"r0.1.0\",\"r0.2.0\",\"r0.3.0\",\"r0.4.0\",\"r0.5.0\"],\"token\":\"MDAxYWxvY2F0aW9uIHVicG9ydHMuY2hhdAowMDEzaWRlbnRpZmllciBrZXkKMDAxMGNpZCBnZW4gPSAxCjAwMjZjaWQgdXNlcl9pZCA9IEBldGVzdDp1YnBvcnRzLmNoYXQKMDAxNmNpZCB0eXBlID0gYWNjZXNzCjAwMjFjaWQgbm9uY2UgPSBHQkBDQ25SYldCaStUbkQ5CjAwMmZzaWduYXR1cmUgoRJsL-s7bzq9MjfAN3ygl9KAKAkAjIrRrqr9V0PyWgEK\",\"userID\":\"@etest:ubports.chat\",\"olmAccount\":null}","/clients/FWTWDQTSXK/rooms/!NMplDtFmBvmtIiWDaa:ubports.chat/session_keys":"{}","/clients/FWTWDQTSXK/rooms/!LYRTvuBiZMyRGBADSe:ubports.chat/session_keys":"{}","/clients/FWTWDQTSXK/rooms/!WyihYMAfvwVpokHAjR:ubports.chat/session_keys":"{}","FluffyChat linux.user_device_keys":"{\"@etest:ubports.chat\":{\"user_id\":\"@etest:ubports.chat\",\"outdated\":false,\"device_keys\":{}}}"}

View File

@ -35,14 +35,14 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
version: "2.4.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
version: "2.0.0"
bubble:
dependency: "direct main"
description:
@ -63,14 +63,21 @@ packages:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
version: "1.1.3"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.11"
version: "1.14.12"
convert:
dependency: transitive
description:
@ -85,6 +92,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.6"
cross_local_storage:
dependency: "direct main"
description:
name: cross_local_storage
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
crypto:
dependency: transitive
description:
@ -113,6 +127,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.3"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
famedlysdk:
dependency: "direct main"
description:
@ -281,7 +302,7 @@ packages:
name: intl
url: "https://pub.dartlang.org"
source: hosted
version: "0.16.0"
version: "0.16.1"
intl_translation:
dependency: "direct main"
description:
@ -310,13 +331,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.1"
localstorage:
dependency: "direct main"
description:
name: localstorage
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1+4"
logging:
dependency: transitive
description:
@ -425,7 +439,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.4"
version: "1.7.0"
path_drawing:
dependency: transitive
description:
@ -503,13 +517,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.2"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
receive_sharing_intent:
dependency: "direct main"
description:
@ -524,6 +531,34 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3+5"
shared_preferences:
dependency: transitive
description:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.7"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1+7"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2+4"
shelf:
dependency: transitive
description:
@ -577,7 +612,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.5"
version: "1.7.0"
sqflite:
dependency: "direct main"
description:
@ -613,6 +648,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
system:
dependency: "direct main"
description:
name: system
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
term_glyph:
dependency: transitive
description:
@ -626,21 +668,21 @@ packages:
name: test
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.4"
version: "1.13.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.11"
version: "0.2.15"
test_core:
dependency: transitive
description:
name: test_core
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.15"
version: "0.3.1"
typed_data:
dependency: transitive
description:
@ -725,6 +767,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.0+1"
webview_flutter:
dependency: "direct main"
description:

View File

@ -29,7 +29,7 @@ dependencies:
url: https://gitlab.com/famedly/famedlysdk.git
ref: 28dee0e2e3dc2fdde64b29d0a65028b49b4c4dc7
localstorage: ^3.0.1+4
cross_local_storage: ^1.1.1
bubble: ^1.1.9+1
file_picker: ^1.4.3+2
image_picker: ^0.6.2+3
@ -54,6 +54,7 @@ dependencies:
open_file: ^3.0.1
mime_type: ^0.2.7
flutter_styled_toast: ^1.2.1
system: ^0.2.0
intl: ^0.16.0
intl_translation: ^0.17.9