fix: Récupérer l'opération active depuis la table operations
- Corrige l'erreur SQL 'Unknown column fk_operation in users' - L'opération active est récupérée depuis operations.chk_active = 1 - Jointure avec users pour filtrer par entité de l'admin créateur - Query: SELECT o.id FROM operations o INNER JOIN users u ON u.fk_entite = o.fk_entite WHERE u.id = ? AND o.chk_active = 1
This commit is contained in:
@@ -1 +0,0 @@
|
||||
/home/pierre/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1/
|
||||
66
app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/AUTHORS
Executable file
66
app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/AUTHORS
Executable file
@@ -0,0 +1,66 @@
|
||||
# Below is a list of people and organizations that have contributed
|
||||
# to the Flutter project. Names should be added to the list like so:
|
||||
#
|
||||
# Name/Organization <email address>
|
||||
|
||||
Google Inc.
|
||||
The Chromium Authors
|
||||
German Saprykin <saprykin.h@gmail.com>
|
||||
Benjamin Sauer <sauer.benjamin@gmail.com>
|
||||
larsenthomasj@gmail.com
|
||||
Ali Bitek <alibitek@protonmail.ch>
|
||||
Pol Batlló <pol.batllo@gmail.com>
|
||||
Anatoly Pulyaevskiy
|
||||
Hayden Flinner <haydenflinner@gmail.com>
|
||||
Stefano Rodriguez <hlsroddy@gmail.com>
|
||||
Salvatore Giordano <salvatoregiordanoo@gmail.com>
|
||||
Brian Armstrong <brian@flutter.institute>
|
||||
Paul DeMarco <paulmdemarco@gmail.com>
|
||||
Fabricio Nogueira <feufeu@gmail.com>
|
||||
Simon Lightfoot <simon@devangels.london>
|
||||
Ashton Thomas <ashton@acrinta.com>
|
||||
Thomas Danner <thmsdnnr@gmail.com>
|
||||
Diego Velásquez <diego.velasquez.lopez@gmail.com>
|
||||
Hajime Nakamura <nkmrhj@gmail.com>
|
||||
Tuyển Vũ Xuân <netsoft1985@gmail.com>
|
||||
Miguel Ruivo <miguel@miguelruivo.com>
|
||||
Sarthak Verma <sarthak@artiosys.com>
|
||||
Mike Diarmid <mike@invertase.io>
|
||||
Invertase <oss@invertase.io>
|
||||
Elliot Hesp <elliot@invertase.io>
|
||||
Vince Varga <vince.varga@smaho.com>
|
||||
Aawaz Gyawali <awazgyawali@gmail.com>
|
||||
EUI Limited <ian.evans3@admiralgroup.co.uk>
|
||||
Katarina Sheremet <katarina@sheremet.ch>
|
||||
Thomas Stockx <thomas@stockxit.com>
|
||||
Sarbagya Dhaubanjar <sarbagyastha@gmail.com>
|
||||
Ozkan Eksi <ozeksi@gmail.com>
|
||||
Rishab Nayak <rishab@bu.edu>
|
||||
ko2ic <ko2ic.dev@gmail.com>
|
||||
Jonathan Younger <jonathan@daikini.com>
|
||||
Jose Sanchez <josesm82@gmail.com>
|
||||
Debkanchan Samadder <debu.samadder@gmail.com>
|
||||
Audrius Karosevicius <audrius.karosevicius@gmail.com>
|
||||
Lukasz Piliszczuk <lukasz@intheloup.io>
|
||||
SoundReply Solutions GmbH <ch@soundreply.com>
|
||||
Rafal Wachol <rwachol@gmail.com>
|
||||
Pau Picas <pau.picas@gmail.com>
|
||||
Christian Weder <chrstian.weder@yapeal.ch>
|
||||
Alexandru Tuca <salexandru.tuca@outlook.com>
|
||||
Christian Weder <chrstian.weder@yapeal.ch>
|
||||
Rhodes Davis Jr. <rody.davis.jr@gmail.com>
|
||||
Luigi Agosti <luigi@tengio.com>
|
||||
Quentin Le Guennec <quentin@tengio.com>
|
||||
Koushik Ravikumar <koushik@tengio.com>
|
||||
Nissim Dsilva <nissim@tengio.com>
|
||||
Giancarlo Rocha <giancarloiff@gmail.com>
|
||||
Ryo Miyake <ryo@miyake.id>
|
||||
Théo Champion <contact.theochampion@gmail.com>
|
||||
Kazuki Yamaguchi <y.kazuki0614n@gmail.com>
|
||||
Eitan Schwartz <eshvartz@gmail.com>
|
||||
Chris Rutkowski <chrisrutkowski89@gmail.com>
|
||||
Juan Alvarez <juan.alvarez@resideo.com>
|
||||
Aleksandr Yurkovskiy <sanekyy@gmail.com>
|
||||
Anton Borries <mail@antonborri.es>
|
||||
Alex Li <google@alexv525.com>
|
||||
Rahul Raj <64.rahulraj@gmail.com>
|
||||
105
app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/CHANGELOG.md
Executable file
105
app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/CHANGELOG.md
Executable file
@@ -0,0 +1,105 @@
|
||||
## 3.2.1
|
||||
|
||||
* Updates Pigeon to resolve a compilation failure with some versions of glib.
|
||||
|
||||
## 3.2.0
|
||||
|
||||
* Updates platform channels to use Pigeon.
|
||||
* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3.
|
||||
|
||||
## 3.1.1
|
||||
|
||||
* Implements `launchUrl`.
|
||||
* Simplifies method channel interface by removing unused elements.
|
||||
* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0.
|
||||
|
||||
## 3.1.0
|
||||
|
||||
* Implements `supportsMode` and `supportsCloseForMode`.
|
||||
|
||||
## 3.0.6
|
||||
|
||||
* Adds pub topics to package metadata.
|
||||
* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19.
|
||||
|
||||
## 3.0.5
|
||||
|
||||
* Sets a cmake_policy compatibility version to fix build warnings.
|
||||
|
||||
## 3.0.4
|
||||
|
||||
* Clarifies explanation of endorsement in README.
|
||||
* Aligns Dart and Flutter SDK constraints.
|
||||
|
||||
## 3.0.3
|
||||
|
||||
* Updates links for the merge of flutter/plugins into flutter/packages.
|
||||
* Updates minimum Flutter version to 3.0.
|
||||
|
||||
## 3.0.2
|
||||
|
||||
* Updates code for stricter lint checks.
|
||||
* Updates minimum Flutter version to 2.10.
|
||||
|
||||
## 3.0.1
|
||||
|
||||
* Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors
|
||||
lint warnings.
|
||||
|
||||
## 3.0.0
|
||||
|
||||
* Changes the major version since, due to a typo in `default_package` in
|
||||
existing versions of `url_launcher`, requiring Dart registration in this
|
||||
package is in practice a breaking change.
|
||||
* Does not include any API changes; clients can allow both 2.x or 3.x.
|
||||
|
||||
## 2.0.4
|
||||
|
||||
* **\[Retracted\]** Switches to an in-package method channel implementation.
|
||||
|
||||
## 2.0.3
|
||||
|
||||
* Updates code for new analysis options.
|
||||
* Fix minor memory leak in Linux url_launcher tests.
|
||||
* Fixes canLaunch detection for URIs addressing on local or network file systems
|
||||
|
||||
## 2.0.2
|
||||
|
||||
* Replaced reference to `shared_preferences` plugin with the `url_launcher` in the README.
|
||||
|
||||
## 2.0.1
|
||||
|
||||
* Updated installation instructions in README.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
* Migrate to null safety.
|
||||
* Update the example app: remove the deprecated `RaisedButton` and `FlatButton` widgets.
|
||||
* Fix outdated links across a number of markdown files ([#3276](https://github.com/flutter/plugins/pull/3276))
|
||||
* Set `implementation` in pubspec.yaml
|
||||
|
||||
## 0.0.2+1
|
||||
|
||||
* Update Flutter SDK constraint.
|
||||
|
||||
## 0.0.2
|
||||
|
||||
* Update integration test examples to use `testWidgets` instead of `test`.
|
||||
|
||||
## 0.0.1+4
|
||||
|
||||
* Update Dart SDK constraint in example.
|
||||
|
||||
## 0.0.1+3
|
||||
|
||||
* Add a missing include.
|
||||
|
||||
## 0.0.1+2
|
||||
|
||||
* Check in linux/ directory for example/
|
||||
|
||||
# 0.0.1+1
|
||||
* README update for endorsement by url_launcher.
|
||||
|
||||
# 0.0.1
|
||||
* The initial implementation of url_launcher for Linux
|
||||
25
app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/LICENSE
Executable file
25
app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/LICENSE
Executable file
@@ -0,0 +1,25 @@
|
||||
Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
15
app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/README.md
Executable file
15
app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/README.md
Executable file
@@ -0,0 +1,15 @@
|
||||
# url\_launcher\_linux
|
||||
|
||||
The Linux implementation of [`url_launcher`][1].
|
||||
|
||||
## Usage
|
||||
|
||||
This package is [endorsed][2], which means you can simply use `url_launcher`
|
||||
normally. This package will be automatically included in your app when you do,
|
||||
so you do not need to add it to your `pubspec.yaml`.
|
||||
|
||||
However, if you `import` this package to use any of its APIs directly, you
|
||||
should add it to your `pubspec.yaml` as usual.
|
||||
|
||||
[1]: https://pub.dev/packages/url_launcher
|
||||
[2]: https://flutter.dev/to/endorsed-federated-plugin
|
||||
@@ -0,0 +1,9 @@
|
||||
# Platform Implementation Test App
|
||||
|
||||
This is a test app for manual testing and automated integration testing
|
||||
of this platform implementation. It is not intended to demonstrate actual use of
|
||||
this package, since the intent is that plugin clients use the app-facing
|
||||
package.
|
||||
|
||||
Unless you are making changes to this implementation package, this example is
|
||||
very unlikely to be relevant.
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
testWidgets('canLaunch', (WidgetTester _) async {
|
||||
final UrlLauncherPlatform launcher = UrlLauncherPlatform.instance;
|
||||
|
||||
expect(await launcher.canLaunch('randomstring'), false);
|
||||
|
||||
// Generally all devices should have some default browser.
|
||||
expect(await launcher.canLaunch('http://flutter.dev'), true);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// ignore_for_file: public_member_api_docs
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'URL Launcher',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
),
|
||||
home: const MyHomePage(title: 'URL Launcher'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
Future<void>? _launched;
|
||||
|
||||
Future<void> _launchInBrowser(String url) async {
|
||||
if (await UrlLauncherPlatform.instance.canLaunch(url)) {
|
||||
await UrlLauncherPlatform.instance.launch(
|
||||
url,
|
||||
useSafariVC: false,
|
||||
useWebView: false,
|
||||
enableJavaScript: false,
|
||||
enableDomStorage: false,
|
||||
universalLinksOnly: false,
|
||||
headers: <String, String>{},
|
||||
);
|
||||
} else {
|
||||
throw Exception('Could not launch $url');
|
||||
}
|
||||
}
|
||||
|
||||
Widget _launchStatus(BuildContext context, AsyncSnapshot<void> snapshot) {
|
||||
if (snapshot.hasError) {
|
||||
return Text('Error: ${snapshot.error}');
|
||||
} else {
|
||||
return const Text('');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const String toLaunch = 'https://www.cylog.org/headers/';
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(widget.title),
|
||||
),
|
||||
body: ListView(
|
||||
children: <Widget>[
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Text(toLaunch),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () => setState(() {
|
||||
_launched = _launchInBrowser(toLaunch);
|
||||
}),
|
||||
child: const Text('Launch in browser'),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(16.0)),
|
||||
FutureBuilder<void>(future: _launched, builder: _launchStatus),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(runner LANGUAGES CXX)
|
||||
|
||||
set(BINARY_NAME "example")
|
||||
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
||||
|
||||
# Configure build options.
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||
STRING "Flutter build mode" FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Profile" "Release")
|
||||
endif()
|
||||
|
||||
# Compilation settings that should be applied to most targets.
|
||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
||||
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
||||
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
||||
endfunction()
|
||||
|
||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||
|
||||
# Flutter library and tool build rules.
|
||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||
|
||||
# System-level dependencies.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||
|
||||
# Application build
|
||||
add_executable(${BINARY_NAME}
|
||||
"main.cc"
|
||||
"my_application.cc"
|
||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||
)
|
||||
apply_standard_settings(${BINARY_NAME})
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||
|
||||
# Enable the test target.
|
||||
set(include_url_launcher_linux_tests TRUE)
|
||||
# Provide an alias for the test target using the name expected by repo tooling.
|
||||
add_custom_target(unit_tests DEPENDS url_launcher_linux_test)
|
||||
|
||||
# Generated plugin build rules, which manage building the plugins and adding
|
||||
# them to the application.
|
||||
include(flutter/generated_plugins.cmake)
|
||||
|
||||
|
||||
# === Installation ===
|
||||
# By default, "installing" just makes a relocatable bundle in the build
|
||||
# directory.
|
||||
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
# Start with a clean build bundle directory every time.
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
|
||||
" COMPONENT Runtime)
|
||||
|
||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
|
||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
if(PLUGIN_BUNDLED_LIBRARIES)
|
||||
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
|
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||
# from a previous install.
|
||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||
" COMPONENT Runtime)
|
||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||
|
||||
# Install the AOT library on non-Debug builds only.
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endif()
|
||||
@@ -0,0 +1,87 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||
|
||||
# Configuration provided via flutter tool.
|
||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||
|
||||
# TODO: Move the rest of this into files in ephemeral. See
|
||||
# https://github.com/flutter/flutter/issues/57146.
|
||||
|
||||
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
|
||||
# which isn't available in 3.10.
|
||||
function(list_prepend LIST_NAME PREFIX)
|
||||
set(NEW_LIST "")
|
||||
foreach(element ${${LIST_NAME}})
|
||||
list(APPEND NEW_LIST "${PREFIX}${element}")
|
||||
endforeach(element)
|
||||
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# === Flutter Library ===
|
||||
# System-level dependencies.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
|
||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
||||
|
||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
|
||||
|
||||
# Published to parent scope for install step.
|
||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
|
||||
|
||||
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||
"fl_basic_message_channel.h"
|
||||
"fl_binary_codec.h"
|
||||
"fl_binary_messenger.h"
|
||||
"fl_dart_project.h"
|
||||
"fl_engine.h"
|
||||
"fl_json_message_codec.h"
|
||||
"fl_json_method_codec.h"
|
||||
"fl_message_codec.h"
|
||||
"fl_method_call.h"
|
||||
"fl_method_channel.h"
|
||||
"fl_method_codec.h"
|
||||
"fl_method_response.h"
|
||||
"fl_plugin_registrar.h"
|
||||
"fl_plugin_registry.h"
|
||||
"fl_standard_message_codec.h"
|
||||
"fl_standard_method_codec.h"
|
||||
"fl_string_codec.h"
|
||||
"fl_value.h"
|
||||
"fl_view.h"
|
||||
"flutter_linux.h"
|
||||
)
|
||||
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
|
||||
add_library(flutter INTERFACE)
|
||||
target_include_directories(flutter INTERFACE
|
||||
"${EPHEMERAL_DIR}"
|
||||
)
|
||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
|
||||
target_link_libraries(flutter INTERFACE
|
||||
PkgConfig::GTK
|
||||
PkgConfig::GLIB
|
||||
PkgConfig::GIO
|
||||
)
|
||||
add_dependencies(flutter flutter_assemble)
|
||||
|
||||
# === Flutter tool backend ===
|
||||
# _phony_ is a non-existent file to force this command to run every time,
|
||||
# since currently there's no way to get a full input/output list from the
|
||||
# flutter tool.
|
||||
add_custom_command(
|
||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/_phony_
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
${FLUTTER_TOOL_ENVIRONMENT}
|
||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
|
||||
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(flutter_assemble DEPENDS
|
||||
"${FLUTTER_LIBRARY}"
|
||||
${FLUTTER_LIBRARY_HEADERS}
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||
endforeach(plugin)
|
||||
|
||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||
endforeach(ffi_plugin)
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "my_application.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
g_autoptr(MyApplication) app = my_application_new();
|
||||
return g_application_run(G_APPLICATION(app), argc, argv);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "my_application.h"
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
#include "flutter/generated_plugin_registrant.h"
|
||||
|
||||
struct _MyApplication {
|
||||
GtkApplication parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
|
||||
|
||||
// Implements GApplication::activate.
|
||||
static void my_application_activate(GApplication* application) {
|
||||
GtkWindow* window =
|
||||
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
|
||||
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||
gtk_header_bar_set_title(header_bar, "example");
|
||||
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||
gtk_window_set_default_size(window, 1280, 720);
|
||||
gtk_widget_show(GTK_WIDGET(window));
|
||||
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||
|
||||
FlView* view = fl_view_new(project);
|
||||
gtk_widget_show(GTK_WIDGET(view));
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||
|
||||
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
||||
|
||||
gtk_widget_grab_focus(GTK_WIDGET(view));
|
||||
}
|
||||
|
||||
static void my_application_class_init(MyApplicationClass* klass) {
|
||||
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
|
||||
}
|
||||
|
||||
static void my_application_init(MyApplication* self) {}
|
||||
|
||||
MyApplication* my_application_new() {
|
||||
return MY_APPLICATION(g_object_new(my_application_get_type(), nullptr));
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_MY_APPLICATION_H_
|
||||
#define FLUTTER_MY_APPLICATION_H_
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
|
||||
GtkApplication)
|
||||
|
||||
/**
|
||||
* my_application_new:
|
||||
*
|
||||
* Creates a new Flutter-based application.
|
||||
*
|
||||
* Returns: a new #MyApplication.
|
||||
*/
|
||||
MyApplication* my_application_new();
|
||||
|
||||
#endif // FLUTTER_MY_APPLICATION_H_
|
||||
@@ -0,0 +1,28 @@
|
||||
name: url_launcher_example
|
||||
description: Demonstrates how to use the url_launcher plugin.
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ^3.3.0
|
||||
flutter: ">=3.19.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
url_launcher_linux:
|
||||
# When depending on this package from a real application you should use:
|
||||
# url_launcher_linux: ^x.y.z
|
||||
# See https://dart.dev/tools/pub/dependencies#version-constraints
|
||||
# The example app is bundled with the plugin so we use a path dependency on
|
||||
# the parent directory to use the current plugin's version.
|
||||
path: ../
|
||||
url_launcher_platform_interface: ^2.2.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
integration_test:
|
||||
sdk: flutter
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:integration_test/integration_test_driver.dart';
|
||||
|
||||
Future<void> main() => integrationDriver();
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:url_launcher_platform_interface/link.dart';
|
||||
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
|
||||
|
||||
import 'src/messages.g.dart';
|
||||
|
||||
/// An implementation of [UrlLauncherPlatform] for Linux.
|
||||
class UrlLauncherLinux extends UrlLauncherPlatform {
|
||||
/// Creates a new URL launcher instance.
|
||||
UrlLauncherLinux({@visibleForTesting UrlLauncherApi? api})
|
||||
: _hostApi = api ?? UrlLauncherApi();
|
||||
|
||||
/// Registers this class as the default instance of [UrlLauncherPlatform].
|
||||
static void registerWith() {
|
||||
UrlLauncherPlatform.instance = UrlLauncherLinux();
|
||||
}
|
||||
|
||||
final UrlLauncherApi _hostApi;
|
||||
|
||||
@override
|
||||
final LinkDelegate? linkDelegate = null;
|
||||
|
||||
@override
|
||||
Future<bool> canLaunch(String url) async {
|
||||
return _hostApi.canLaunchUrl(url);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> launch(
|
||||
String url, {
|
||||
required bool useSafariVC,
|
||||
required bool useWebView,
|
||||
required bool enableJavaScript,
|
||||
required bool enableDomStorage,
|
||||
required bool universalLinksOnly,
|
||||
required Map<String, String> headers,
|
||||
String? webOnlyWindowName,
|
||||
}) {
|
||||
// None of the options are supported, so they don't need to be converted to
|
||||
// LaunchOptions.
|
||||
return launchUrl(url, const LaunchOptions());
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> launchUrl(String url, LaunchOptions options) async {
|
||||
final String? error = await _hostApi.launchUrl(url);
|
||||
if (error != null) {
|
||||
// TODO(stuartmorgan): Standardize errors across the entire plugin,
|
||||
// instead of using PlatformException. This preserves the pre-Pigeon
|
||||
// behavior of the C code returning this error response.
|
||||
throw PlatformException(
|
||||
code: 'Launch Error', message: 'Failed to launch URL: $error');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> supportsMode(PreferredLaunchMode mode) async {
|
||||
return mode == PreferredLaunchMode.platformDefault ||
|
||||
mode == PreferredLaunchMode.externalApplication;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> supportsCloseForMode(PreferredLaunchMode mode) async {
|
||||
// No supported mode is closeable.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
set(PROJECT_NAME "url_launcher_linux")
|
||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||
|
||||
cmake_policy(VERSION 3.10...3.24)
|
||||
|
||||
set(PLUGIN_NAME "${PROJECT_NAME}_plugin")
|
||||
|
||||
list(APPEND PLUGIN_SOURCES
|
||||
"messages.g.cc"
|
||||
"url_launcher_plugin.cc"
|
||||
)
|
||||
|
||||
add_library(${PLUGIN_NAME} SHARED
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
apply_standard_settings(${PLUGIN_NAME})
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden)
|
||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
|
||||
target_include_directories(${PLUGIN_NAME} INTERFACE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)
|
||||
|
||||
|
||||
# === Tests ===
|
||||
|
||||
if (${include_${PROJECT_NAME}_tests})
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.11.0")
|
||||
message("Unit tests require CMake 3.11.0 or later")
|
||||
else()
|
||||
set(TEST_RUNNER "${PROJECT_NAME}_test")
|
||||
enable_testing()
|
||||
# TODO(stuartmorgan): Consider using a single shared, pre-checked-in googletest
|
||||
# instance rather than downloading for each plugin. This approach makes sense
|
||||
# for a template, but not for a monorepo with many plugins.
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/release-1.11.0.zip
|
||||
)
|
||||
# Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
# Disable install commands for gtest so it doesn't end up in the bundle.
|
||||
set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE)
|
||||
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# The plugin's exported API is not very useful for unit testing, so build the
|
||||
# sources directly into the test binary rather than using the shared library.
|
||||
add_executable(${TEST_RUNNER}
|
||||
test/url_launcher_linux_test.cc
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
apply_standard_settings(${TEST_RUNNER})
|
||||
target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE flutter)
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK)
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(${TEST_RUNNER})
|
||||
endif() # CMake version check
|
||||
endif() # include_${PROJECT_NAME}_tests
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef PACKAGES_URL_LAUNCHER_URL_LAUNCHER_LINUX_LINUX_INCLUDE_URL_LAUNCHER_URL_LAUNCHER_PLUGIN_H_
|
||||
#define PACKAGES_URL_LAUNCHER_URL_LAUNCHER_LINUX_LINUX_INCLUDE_URL_LAUNCHER_URL_LAUNCHER_PLUGIN_H_
|
||||
|
||||
// A plugin to launch URLs.
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifdef FLUTTER_PLUGIN_IMPL
|
||||
#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define FLUTTER_PLUGIN_EXPORT
|
||||
#endif
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FlUrlLauncherPlugin, fl_url_launcher_plugin, FL,
|
||||
URL_LAUNCHER_PLUGIN, GObject)
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT FlUrlLauncherPlugin* fl_url_launcher_plugin_new(
|
||||
FlPluginRegistrar* registrar);
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void url_launcher_plugin_register_with_registrar(
|
||||
FlPluginRegistrar* registrar);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // PACKAGES_URL_LAUNCHER_URL_LAUNCHER_LINUX_LINUX_INCLUDE_URL_LAUNCHER_URL_LAUNCHER_PLUGIN_H_
|
||||
@@ -0,0 +1,300 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
// Autogenerated from Pigeon (v22.6.1), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
#include "messages.g.h"
|
||||
|
||||
struct _FulMessageCodec {
|
||||
FlStandardMessageCodec parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FulMessageCodec, ful_message_codec,
|
||||
fl_standard_message_codec_get_type())
|
||||
|
||||
static gboolean ful_message_codec_write_value(FlStandardMessageCodec* codec,
|
||||
GByteArray* buffer,
|
||||
FlValue* value, GError** error) {
|
||||
if (fl_value_get_type(value) == FL_VALUE_TYPE_CUSTOM) {
|
||||
switch (fl_value_get_custom_type(value)) {}
|
||||
}
|
||||
|
||||
return FL_STANDARD_MESSAGE_CODEC_CLASS(ful_message_codec_parent_class)
|
||||
->write_value(codec, buffer, value, error);
|
||||
}
|
||||
|
||||
static FlValue* ful_message_codec_read_value_of_type(
|
||||
FlStandardMessageCodec* codec, GBytes* buffer, size_t* offset, int type,
|
||||
GError** error) {
|
||||
switch (type) {
|
||||
default:
|
||||
return FL_STANDARD_MESSAGE_CODEC_CLASS(ful_message_codec_parent_class)
|
||||
->read_value_of_type(codec, buffer, offset, type, error);
|
||||
}
|
||||
}
|
||||
|
||||
static void ful_message_codec_init(FulMessageCodec* self) {}
|
||||
|
||||
static void ful_message_codec_class_init(FulMessageCodecClass* klass) {
|
||||
FL_STANDARD_MESSAGE_CODEC_CLASS(klass)->write_value =
|
||||
ful_message_codec_write_value;
|
||||
FL_STANDARD_MESSAGE_CODEC_CLASS(klass)->read_value_of_type =
|
||||
ful_message_codec_read_value_of_type;
|
||||
}
|
||||
|
||||
static FulMessageCodec* ful_message_codec_new() {
|
||||
FulMessageCodec* self =
|
||||
FUL_MESSAGE_CODEC(g_object_new(ful_message_codec_get_type(), nullptr));
|
||||
return self;
|
||||
}
|
||||
|
||||
struct _FulUrlLauncherApiCanLaunchUrlResponse {
|
||||
GObject parent_instance;
|
||||
|
||||
FlValue* value;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FulUrlLauncherApiCanLaunchUrlResponse,
|
||||
ful_url_launcher_api_can_launch_url_response, G_TYPE_OBJECT)
|
||||
|
||||
static void ful_url_launcher_api_can_launch_url_response_dispose(
|
||||
GObject* object) {
|
||||
FulUrlLauncherApiCanLaunchUrlResponse* self =
|
||||
FUL_URL_LAUNCHER_API_CAN_LAUNCH_URL_RESPONSE(object);
|
||||
g_clear_pointer(&self->value, fl_value_unref);
|
||||
G_OBJECT_CLASS(ful_url_launcher_api_can_launch_url_response_parent_class)
|
||||
->dispose(object);
|
||||
}
|
||||
|
||||
static void ful_url_launcher_api_can_launch_url_response_init(
|
||||
FulUrlLauncherApiCanLaunchUrlResponse* self) {}
|
||||
|
||||
static void ful_url_launcher_api_can_launch_url_response_class_init(
|
||||
FulUrlLauncherApiCanLaunchUrlResponseClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose =
|
||||
ful_url_launcher_api_can_launch_url_response_dispose;
|
||||
}
|
||||
|
||||
FulUrlLauncherApiCanLaunchUrlResponse*
|
||||
ful_url_launcher_api_can_launch_url_response_new(gboolean return_value) {
|
||||
FulUrlLauncherApiCanLaunchUrlResponse* self =
|
||||
FUL_URL_LAUNCHER_API_CAN_LAUNCH_URL_RESPONSE(g_object_new(
|
||||
ful_url_launcher_api_can_launch_url_response_get_type(), nullptr));
|
||||
self->value = fl_value_new_list();
|
||||
fl_value_append_take(self->value, fl_value_new_bool(return_value));
|
||||
return self;
|
||||
}
|
||||
|
||||
FulUrlLauncherApiCanLaunchUrlResponse*
|
||||
ful_url_launcher_api_can_launch_url_response_new_error(const gchar* code,
|
||||
const gchar* message,
|
||||
FlValue* details) {
|
||||
FulUrlLauncherApiCanLaunchUrlResponse* self =
|
||||
FUL_URL_LAUNCHER_API_CAN_LAUNCH_URL_RESPONSE(g_object_new(
|
||||
ful_url_launcher_api_can_launch_url_response_get_type(), nullptr));
|
||||
self->value = fl_value_new_list();
|
||||
fl_value_append_take(self->value, fl_value_new_string(code));
|
||||
fl_value_append_take(self->value,
|
||||
fl_value_new_string(message != nullptr ? message : ""));
|
||||
fl_value_append_take(self->value, details != nullptr ? fl_value_ref(details)
|
||||
: fl_value_new_null());
|
||||
return self;
|
||||
}
|
||||
|
||||
struct _FulUrlLauncherApiLaunchUrlResponse {
|
||||
GObject parent_instance;
|
||||
|
||||
FlValue* value;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FulUrlLauncherApiLaunchUrlResponse,
|
||||
ful_url_launcher_api_launch_url_response, G_TYPE_OBJECT)
|
||||
|
||||
static void ful_url_launcher_api_launch_url_response_dispose(GObject* object) {
|
||||
FulUrlLauncherApiLaunchUrlResponse* self =
|
||||
FUL_URL_LAUNCHER_API_LAUNCH_URL_RESPONSE(object);
|
||||
g_clear_pointer(&self->value, fl_value_unref);
|
||||
G_OBJECT_CLASS(ful_url_launcher_api_launch_url_response_parent_class)
|
||||
->dispose(object);
|
||||
}
|
||||
|
||||
static void ful_url_launcher_api_launch_url_response_init(
|
||||
FulUrlLauncherApiLaunchUrlResponse* self) {}
|
||||
|
||||
static void ful_url_launcher_api_launch_url_response_class_init(
|
||||
FulUrlLauncherApiLaunchUrlResponseClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose =
|
||||
ful_url_launcher_api_launch_url_response_dispose;
|
||||
}
|
||||
|
||||
FulUrlLauncherApiLaunchUrlResponse*
|
||||
ful_url_launcher_api_launch_url_response_new(const gchar* return_value) {
|
||||
FulUrlLauncherApiLaunchUrlResponse* self =
|
||||
FUL_URL_LAUNCHER_API_LAUNCH_URL_RESPONSE(g_object_new(
|
||||
ful_url_launcher_api_launch_url_response_get_type(), nullptr));
|
||||
self->value = fl_value_new_list();
|
||||
fl_value_append_take(self->value, return_value != nullptr
|
||||
? fl_value_new_string(return_value)
|
||||
: fl_value_new_null());
|
||||
return self;
|
||||
}
|
||||
|
||||
FulUrlLauncherApiLaunchUrlResponse*
|
||||
ful_url_launcher_api_launch_url_response_new_error(const gchar* code,
|
||||
const gchar* message,
|
||||
FlValue* details) {
|
||||
FulUrlLauncherApiLaunchUrlResponse* self =
|
||||
FUL_URL_LAUNCHER_API_LAUNCH_URL_RESPONSE(g_object_new(
|
||||
ful_url_launcher_api_launch_url_response_get_type(), nullptr));
|
||||
self->value = fl_value_new_list();
|
||||
fl_value_append_take(self->value, fl_value_new_string(code));
|
||||
fl_value_append_take(self->value,
|
||||
fl_value_new_string(message != nullptr ? message : ""));
|
||||
fl_value_append_take(self->value, details != nullptr ? fl_value_ref(details)
|
||||
: fl_value_new_null());
|
||||
return self;
|
||||
}
|
||||
|
||||
struct _FulUrlLauncherApi {
|
||||
GObject parent_instance;
|
||||
|
||||
const FulUrlLauncherApiVTable* vtable;
|
||||
gpointer user_data;
|
||||
GDestroyNotify user_data_free_func;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FulUrlLauncherApi, ful_url_launcher_api, G_TYPE_OBJECT)
|
||||
|
||||
static void ful_url_launcher_api_dispose(GObject* object) {
|
||||
FulUrlLauncherApi* self = FUL_URL_LAUNCHER_API(object);
|
||||
if (self->user_data != nullptr) {
|
||||
self->user_data_free_func(self->user_data);
|
||||
}
|
||||
self->user_data = nullptr;
|
||||
G_OBJECT_CLASS(ful_url_launcher_api_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void ful_url_launcher_api_init(FulUrlLauncherApi* self) {}
|
||||
|
||||
static void ful_url_launcher_api_class_init(FulUrlLauncherApiClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose = ful_url_launcher_api_dispose;
|
||||
}
|
||||
|
||||
static FulUrlLauncherApi* ful_url_launcher_api_new(
|
||||
const FulUrlLauncherApiVTable* vtable, gpointer user_data,
|
||||
GDestroyNotify user_data_free_func) {
|
||||
FulUrlLauncherApi* self = FUL_URL_LAUNCHER_API(
|
||||
g_object_new(ful_url_launcher_api_get_type(), nullptr));
|
||||
self->vtable = vtable;
|
||||
self->user_data = user_data;
|
||||
self->user_data_free_func = user_data_free_func;
|
||||
return self;
|
||||
}
|
||||
|
||||
static void ful_url_launcher_api_can_launch_url_cb(
|
||||
FlBasicMessageChannel* channel, FlValue* message_,
|
||||
FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) {
|
||||
FulUrlLauncherApi* self = FUL_URL_LAUNCHER_API(user_data);
|
||||
|
||||
if (self->vtable == nullptr || self->vtable->can_launch_url == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
FlValue* value0 = fl_value_get_list_value(message_, 0);
|
||||
const gchar* url = fl_value_get_string(value0);
|
||||
g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response =
|
||||
self->vtable->can_launch_url(url, self->user_data);
|
||||
if (response == nullptr) {
|
||||
g_warning("No response returned to %s.%s", "UrlLauncherApi",
|
||||
"canLaunchUrl");
|
||||
return;
|
||||
}
|
||||
|
||||
g_autoptr(GError) error = NULL;
|
||||
if (!fl_basic_message_channel_respond(channel, response_handle,
|
||||
response->value, &error)) {
|
||||
g_warning("Failed to send response to %s.%s: %s", "UrlLauncherApi",
|
||||
"canLaunchUrl", error->message);
|
||||
}
|
||||
}
|
||||
|
||||
static void ful_url_launcher_api_launch_url_cb(
|
||||
FlBasicMessageChannel* channel, FlValue* message_,
|
||||
FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) {
|
||||
FulUrlLauncherApi* self = FUL_URL_LAUNCHER_API(user_data);
|
||||
|
||||
if (self->vtable == nullptr || self->vtable->launch_url == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
FlValue* value0 = fl_value_get_list_value(message_, 0);
|
||||
const gchar* url = fl_value_get_string(value0);
|
||||
g_autoptr(FulUrlLauncherApiLaunchUrlResponse) response =
|
||||
self->vtable->launch_url(url, self->user_data);
|
||||
if (response == nullptr) {
|
||||
g_warning("No response returned to %s.%s", "UrlLauncherApi", "launchUrl");
|
||||
return;
|
||||
}
|
||||
|
||||
g_autoptr(GError) error = NULL;
|
||||
if (!fl_basic_message_channel_respond(channel, response_handle,
|
||||
response->value, &error)) {
|
||||
g_warning("Failed to send response to %s.%s: %s", "UrlLauncherApi",
|
||||
"launchUrl", error->message);
|
||||
}
|
||||
}
|
||||
|
||||
void ful_url_launcher_api_set_method_handlers(
|
||||
FlBinaryMessenger* messenger, const gchar* suffix,
|
||||
const FulUrlLauncherApiVTable* vtable, gpointer user_data,
|
||||
GDestroyNotify user_data_free_func) {
|
||||
g_autofree gchar* dot_suffix =
|
||||
suffix != nullptr ? g_strdup_printf(".%s", suffix) : g_strdup("");
|
||||
g_autoptr(FulUrlLauncherApi) api_data =
|
||||
ful_url_launcher_api_new(vtable, user_data, user_data_free_func);
|
||||
|
||||
g_autoptr(FulMessageCodec) codec = ful_message_codec_new();
|
||||
g_autofree gchar* can_launch_url_channel_name = g_strdup_printf(
|
||||
"dev.flutter.pigeon.url_launcher_linux.UrlLauncherApi.canLaunchUrl%s",
|
||||
dot_suffix);
|
||||
g_autoptr(FlBasicMessageChannel) can_launch_url_channel =
|
||||
fl_basic_message_channel_new(messenger, can_launch_url_channel_name,
|
||||
FL_MESSAGE_CODEC(codec));
|
||||
fl_basic_message_channel_set_message_handler(
|
||||
can_launch_url_channel, ful_url_launcher_api_can_launch_url_cb,
|
||||
g_object_ref(api_data), g_object_unref);
|
||||
g_autofree gchar* launch_url_channel_name = g_strdup_printf(
|
||||
"dev.flutter.pigeon.url_launcher_linux.UrlLauncherApi.launchUrl%s",
|
||||
dot_suffix);
|
||||
g_autoptr(FlBasicMessageChannel) launch_url_channel =
|
||||
fl_basic_message_channel_new(messenger, launch_url_channel_name,
|
||||
FL_MESSAGE_CODEC(codec));
|
||||
fl_basic_message_channel_set_message_handler(
|
||||
launch_url_channel, ful_url_launcher_api_launch_url_cb,
|
||||
g_object_ref(api_data), g_object_unref);
|
||||
}
|
||||
|
||||
void ful_url_launcher_api_clear_method_handlers(FlBinaryMessenger* messenger,
|
||||
const gchar* suffix) {
|
||||
g_autofree gchar* dot_suffix =
|
||||
suffix != nullptr ? g_strdup_printf(".%s", suffix) : g_strdup("");
|
||||
|
||||
g_autoptr(FulMessageCodec) codec = ful_message_codec_new();
|
||||
g_autofree gchar* can_launch_url_channel_name = g_strdup_printf(
|
||||
"dev.flutter.pigeon.url_launcher_linux.UrlLauncherApi.canLaunchUrl%s",
|
||||
dot_suffix);
|
||||
g_autoptr(FlBasicMessageChannel) can_launch_url_channel =
|
||||
fl_basic_message_channel_new(messenger, can_launch_url_channel_name,
|
||||
FL_MESSAGE_CODEC(codec));
|
||||
fl_basic_message_channel_set_message_handler(can_launch_url_channel, nullptr,
|
||||
nullptr, nullptr);
|
||||
g_autofree gchar* launch_url_channel_name = g_strdup_printf(
|
||||
"dev.flutter.pigeon.url_launcher_linux.UrlLauncherApi.launchUrl%s",
|
||||
dot_suffix);
|
||||
g_autoptr(FlBasicMessageChannel) launch_url_channel =
|
||||
fl_basic_message_channel_new(messenger, launch_url_channel_name,
|
||||
FL_MESSAGE_CODEC(codec));
|
||||
fl_basic_message_channel_set_message_handler(launch_url_channel, nullptr,
|
||||
nullptr, nullptr);
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
// Autogenerated from Pigeon (v22.6.1), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
#ifndef PIGEON_MESSAGES_G_H_
|
||||
#define PIGEON_MESSAGES_G_H_
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FulMessageCodec, ful_message_codec, FUL, MESSAGE_CODEC,
|
||||
FlStandardMessageCodec)
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FulUrlLauncherApi, ful_url_launcher_api, FUL,
|
||||
URL_LAUNCHER_API, GObject)
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FulUrlLauncherApiCanLaunchUrlResponse,
|
||||
ful_url_launcher_api_can_launch_url_response, FUL,
|
||||
URL_LAUNCHER_API_CAN_LAUNCH_URL_RESPONSE, GObject)
|
||||
|
||||
/**
|
||||
* ful_url_launcher_api_can_launch_url_response_new:
|
||||
*
|
||||
* Creates a new response to UrlLauncherApi.canLaunchUrl.
|
||||
*
|
||||
* Returns: a new #FulUrlLauncherApiCanLaunchUrlResponse
|
||||
*/
|
||||
FulUrlLauncherApiCanLaunchUrlResponse*
|
||||
ful_url_launcher_api_can_launch_url_response_new(gboolean return_value);
|
||||
|
||||
/**
|
||||
* ful_url_launcher_api_can_launch_url_response_new_error:
|
||||
* @code: error code.
|
||||
* @message: error message.
|
||||
* @details: (allow-none): error details or %NULL.
|
||||
*
|
||||
* Creates a new error response to UrlLauncherApi.canLaunchUrl.
|
||||
*
|
||||
* Returns: a new #FulUrlLauncherApiCanLaunchUrlResponse
|
||||
*/
|
||||
FulUrlLauncherApiCanLaunchUrlResponse*
|
||||
ful_url_launcher_api_can_launch_url_response_new_error(const gchar* code,
|
||||
const gchar* message,
|
||||
FlValue* details);
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FulUrlLauncherApiLaunchUrlResponse,
|
||||
ful_url_launcher_api_launch_url_response, FUL,
|
||||
URL_LAUNCHER_API_LAUNCH_URL_RESPONSE, GObject)
|
||||
|
||||
/**
|
||||
* ful_url_launcher_api_launch_url_response_new:
|
||||
*
|
||||
* Creates a new response to UrlLauncherApi.launchUrl.
|
||||
*
|
||||
* Returns: a new #FulUrlLauncherApiLaunchUrlResponse
|
||||
*/
|
||||
FulUrlLauncherApiLaunchUrlResponse*
|
||||
ful_url_launcher_api_launch_url_response_new(const gchar* return_value);
|
||||
|
||||
/**
|
||||
* ful_url_launcher_api_launch_url_response_new_error:
|
||||
* @code: error code.
|
||||
* @message: error message.
|
||||
* @details: (allow-none): error details or %NULL.
|
||||
*
|
||||
* Creates a new error response to UrlLauncherApi.launchUrl.
|
||||
*
|
||||
* Returns: a new #FulUrlLauncherApiLaunchUrlResponse
|
||||
*/
|
||||
FulUrlLauncherApiLaunchUrlResponse*
|
||||
ful_url_launcher_api_launch_url_response_new_error(const gchar* code,
|
||||
const gchar* message,
|
||||
FlValue* details);
|
||||
|
||||
/**
|
||||
* FulUrlLauncherApiVTable:
|
||||
*
|
||||
* Table of functions exposed by UrlLauncherApi to be implemented by the API
|
||||
* provider.
|
||||
*/
|
||||
typedef struct {
|
||||
FulUrlLauncherApiCanLaunchUrlResponse* (*can_launch_url)(const gchar* url,
|
||||
gpointer user_data);
|
||||
FulUrlLauncherApiLaunchUrlResponse* (*launch_url)(const gchar* url,
|
||||
gpointer user_data);
|
||||
} FulUrlLauncherApiVTable;
|
||||
|
||||
/**
|
||||
* ful_url_launcher_api_set_method_handlers:
|
||||
*
|
||||
* @messenger: an #FlBinaryMessenger.
|
||||
* @suffix: (allow-none): a suffix to add to the API or %NULL for none.
|
||||
* @vtable: implementations of the methods in this API.
|
||||
* @user_data: (closure): user data to pass to the functions in @vtable.
|
||||
* @user_data_free_func: (allow-none): a function which gets called to free
|
||||
* @user_data, or %NULL.
|
||||
*
|
||||
* Connects the method handlers in the UrlLauncherApi API.
|
||||
*/
|
||||
void ful_url_launcher_api_set_method_handlers(
|
||||
FlBinaryMessenger* messenger, const gchar* suffix,
|
||||
const FulUrlLauncherApiVTable* vtable, gpointer user_data,
|
||||
GDestroyNotify user_data_free_func);
|
||||
|
||||
/**
|
||||
* ful_url_launcher_api_clear_method_handlers:
|
||||
*
|
||||
* @messenger: an #FlBinaryMessenger.
|
||||
* @suffix: (allow-none): a suffix to add to the API or %NULL for none.
|
||||
*
|
||||
* Clears the method handlers in the UrlLauncherApi API.
|
||||
*/
|
||||
void ful_url_launcher_api_clear_method_handlers(FlBinaryMessenger* messenger,
|
||||
const gchar* suffix);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // PIGEON_MESSAGES_G_H_
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "include/url_launcher_linux/url_launcher_plugin.h"
|
||||
#include "url_launcher_plugin_private.h"
|
||||
|
||||
// Re-declare the opaque struct as a temporary workaround for the lack of
|
||||
// APIs for reading host API response objects.
|
||||
// TODO(stuartmorgan): Remove this once the following is fixed:
|
||||
// https://github.com/flutter/flutter/issues/152166.
|
||||
struct _FulUrlLauncherApiCanLaunchUrlResponse {
|
||||
GObject parent_instance;
|
||||
|
||||
FlValue* value;
|
||||
};
|
||||
|
||||
namespace url_launcher_plugin {
|
||||
namespace test {
|
||||
|
||||
TEST(UrlLauncherPlugin, CanLaunchSuccess) {
|
||||
g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response =
|
||||
handle_can_launch_url("https://flutter.dev", nullptr);
|
||||
ASSERT_NE(response, nullptr);
|
||||
ASSERT_TRUE(fl_value_get_type(response->value) == FL_VALUE_TYPE_LIST);
|
||||
ASSERT_TRUE(fl_value_get_length(response->value) == 1);
|
||||
g_autoptr(FlValue) expected = fl_value_new_bool(true);
|
||||
EXPECT_TRUE(
|
||||
fl_value_equal(fl_value_get_list_value(response->value, 0), expected));
|
||||
}
|
||||
|
||||
TEST(UrlLauncherPlugin, CanLaunchFailureUnhandled) {
|
||||
g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response =
|
||||
handle_can_launch_url("madeup:scheme", nullptr);
|
||||
ASSERT_NE(response, nullptr);
|
||||
ASSERT_TRUE(fl_value_get_type(response->value) == FL_VALUE_TYPE_LIST);
|
||||
ASSERT_TRUE(fl_value_get_length(response->value) == 1);
|
||||
g_autoptr(FlValue) expected = fl_value_new_bool(false);
|
||||
EXPECT_TRUE(
|
||||
fl_value_equal(fl_value_get_list_value(response->value, 0), expected));
|
||||
}
|
||||
|
||||
TEST(UrlLauncherPlugin, CanLaunchFileSuccess) {
|
||||
g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response =
|
||||
handle_can_launch_url("file:///", nullptr);
|
||||
ASSERT_NE(response, nullptr);
|
||||
ASSERT_TRUE(fl_value_get_type(response->value) == FL_VALUE_TYPE_LIST);
|
||||
ASSERT_TRUE(fl_value_get_length(response->value) == 1);
|
||||
g_autoptr(FlValue) expected = fl_value_new_bool(true);
|
||||
EXPECT_TRUE(
|
||||
fl_value_equal(fl_value_get_list_value(response->value, 0), expected));
|
||||
}
|
||||
|
||||
TEST(UrlLauncherPlugin, CanLaunchFailureInvalidFileExtension) {
|
||||
g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response =
|
||||
handle_can_launch_url("file:///madeup.madeupextension", nullptr);
|
||||
ASSERT_NE(response, nullptr);
|
||||
ASSERT_TRUE(fl_value_get_type(response->value) == FL_VALUE_TYPE_LIST);
|
||||
ASSERT_TRUE(fl_value_get_length(response->value) == 1);
|
||||
g_autoptr(FlValue) expected = fl_value_new_bool(false);
|
||||
EXPECT_TRUE(
|
||||
fl_value_equal(fl_value_get_list_value(response->value, 0), expected));
|
||||
}
|
||||
|
||||
// For consistency with the established mobile implementations,
|
||||
// an invalid URL should return false, not an error.
|
||||
TEST(UrlLauncherPlugin, CanLaunchFailureInvalidUrl) {
|
||||
g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response =
|
||||
handle_can_launch_url("", nullptr);
|
||||
ASSERT_NE(response, nullptr);
|
||||
ASSERT_TRUE(fl_value_get_type(response->value) == FL_VALUE_TYPE_LIST);
|
||||
ASSERT_TRUE(fl_value_get_length(response->value) == 1);
|
||||
g_autoptr(FlValue) expected = fl_value_new_bool(false);
|
||||
EXPECT_TRUE(
|
||||
fl_value_equal(fl_value_get_list_value(response->value, 0), expected));
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace url_launcher_plugin
|
||||
@@ -0,0 +1,109 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "include/url_launcher_linux/url_launcher_plugin.h"
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "messages.g.h"
|
||||
#include "url_launcher_plugin_private.h"
|
||||
|
||||
struct _FlUrlLauncherPlugin {
|
||||
GObject parent_instance;
|
||||
|
||||
FlPluginRegistrar* registrar;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FlUrlLauncherPlugin, fl_url_launcher_plugin, g_object_get_type())
|
||||
|
||||
// Checks if URI has launchable file resource.
|
||||
static gboolean can_launch_uri_with_file_resource(FlUrlLauncherPlugin* self,
|
||||
const gchar* url) {
|
||||
g_autoptr(GError) error = nullptr;
|
||||
g_autoptr(GFile) file = g_file_new_for_uri(url);
|
||||
g_autoptr(GAppInfo) app_info =
|
||||
g_file_query_default_handler(file, NULL, &error);
|
||||
return app_info != nullptr;
|
||||
}
|
||||
|
||||
FulUrlLauncherApiCanLaunchUrlResponse* handle_can_launch_url(
|
||||
const gchar* url, gpointer user_data) {
|
||||
FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN(user_data);
|
||||
|
||||
gboolean is_launchable = FALSE;
|
||||
g_autofree gchar* scheme = g_uri_parse_scheme(url);
|
||||
if (scheme != nullptr) {
|
||||
g_autoptr(GAppInfo) app_info =
|
||||
g_app_info_get_default_for_uri_scheme(scheme);
|
||||
is_launchable = app_info != nullptr;
|
||||
|
||||
if (!is_launchable) {
|
||||
is_launchable = can_launch_uri_with_file_resource(self, url);
|
||||
}
|
||||
}
|
||||
|
||||
return ful_url_launcher_api_can_launch_url_response_new(is_launchable);
|
||||
}
|
||||
|
||||
// Called when a URL should launch.
|
||||
static FulUrlLauncherApiLaunchUrlResponse* handle_launch_url(
|
||||
const gchar* url, gpointer user_data) {
|
||||
FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN(user_data);
|
||||
|
||||
FlView* view = fl_plugin_registrar_get_view(self->registrar);
|
||||
g_autoptr(GError) error = nullptr;
|
||||
gboolean launched;
|
||||
if (view != nullptr) {
|
||||
GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view)));
|
||||
launched = gtk_show_uri_on_window(window, url, GDK_CURRENT_TIME, &error);
|
||||
} else {
|
||||
launched = g_app_info_launch_default_for_uri(url, nullptr, &error);
|
||||
}
|
||||
if (!launched) {
|
||||
return ful_url_launcher_api_launch_url_response_new(error->message);
|
||||
}
|
||||
|
||||
return ful_url_launcher_api_launch_url_response_new(nullptr);
|
||||
}
|
||||
|
||||
static void fl_url_launcher_plugin_dispose(GObject* object) {
|
||||
FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN(object);
|
||||
|
||||
ful_url_launcher_api_clear_method_handlers(
|
||||
fl_plugin_registrar_get_messenger(self->registrar), nullptr);
|
||||
g_clear_object(&self->registrar);
|
||||
|
||||
G_OBJECT_CLASS(fl_url_launcher_plugin_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void fl_url_launcher_plugin_class_init(FlUrlLauncherPluginClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose = fl_url_launcher_plugin_dispose;
|
||||
}
|
||||
|
||||
FlUrlLauncherPlugin* fl_url_launcher_plugin_new(FlPluginRegistrar* registrar) {
|
||||
FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN(
|
||||
g_object_new(fl_url_launcher_plugin_get_type(), nullptr));
|
||||
|
||||
self->registrar = FL_PLUGIN_REGISTRAR(g_object_ref(registrar));
|
||||
|
||||
static FulUrlLauncherApiVTable api_vtable = {
|
||||
.can_launch_url = handle_can_launch_url,
|
||||
.launch_url = handle_launch_url,
|
||||
};
|
||||
ful_url_launcher_api_set_method_handlers(
|
||||
fl_plugin_registrar_get_messenger(registrar), nullptr, &api_vtable,
|
||||
g_object_ref(self), g_object_unref);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void fl_url_launcher_plugin_init(FlUrlLauncherPlugin* self) {}
|
||||
|
||||
void url_launcher_plugin_register_with_registrar(FlPluginRegistrar* registrar) {
|
||||
FlUrlLauncherPlugin* plugin = fl_url_launcher_plugin_new(registrar);
|
||||
g_object_unref(plugin);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
#include "include/url_launcher_linux/url_launcher_plugin.h"
|
||||
#include "messages.g.h"
|
||||
|
||||
// Called to check if a URL can be launched.
|
||||
FulUrlLauncherApiCanLaunchUrlResponse* handle_can_launch_url(
|
||||
const gchar* url, gpointer user_data);
|
||||
@@ -0,0 +1,3 @@
|
||||
Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style license that can be
|
||||
found in the LICENSE file.
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:pigeon/pigeon.dart';
|
||||
|
||||
@ConfigurePigeon(PigeonOptions(
|
||||
dartOut: 'lib/src/messages.g.dart',
|
||||
gobjectHeaderOut: 'linux/messages.g.h',
|
||||
gobjectSourceOut: 'linux/messages.g.cc',
|
||||
gobjectOptions: GObjectOptions(module: 'Ful'),
|
||||
copyrightHeader: 'pigeons/copyright.txt',
|
||||
))
|
||||
@HostApi()
|
||||
abstract class UrlLauncherApi {
|
||||
/// Returns true if the URL can definitely be launched.
|
||||
bool canLaunchUrl(String url);
|
||||
|
||||
/// Opens the URL externally, returning an error string on failure.
|
||||
String? launchUrl(String url);
|
||||
}
|
||||
34
app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pubspec.yaml
Executable file
34
app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pubspec.yaml
Executable file
@@ -0,0 +1,34 @@
|
||||
name: url_launcher_linux
|
||||
description: Linux implementation of the url_launcher plugin.
|
||||
repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher_linux
|
||||
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22
|
||||
version: 3.2.1
|
||||
|
||||
environment:
|
||||
sdk: ^3.3.0
|
||||
flutter: ">=3.19.0"
|
||||
|
||||
flutter:
|
||||
plugin:
|
||||
implements: url_launcher
|
||||
platforms:
|
||||
linux:
|
||||
pluginClass: UrlLauncherPlugin
|
||||
dartPluginClass: UrlLauncherLinux
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
url_launcher_platform_interface: ^2.2.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
pigeon: ^22.6.1
|
||||
test: ^1.16.3
|
||||
|
||||
topics:
|
||||
- links
|
||||
- os-integration
|
||||
- url-launcher
|
||||
- urls
|
||||
@@ -0,0 +1,175 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:url_launcher_linux/src/messages.g.dart';
|
||||
import 'package:url_launcher_linux/url_launcher_linux.dart';
|
||||
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
|
||||
|
||||
void main() {
|
||||
group('UrlLauncherLinux', () {
|
||||
test('registers instance', () {
|
||||
UrlLauncherLinux.registerWith();
|
||||
expect(UrlLauncherPlatform.instance, isA<UrlLauncherLinux>());
|
||||
});
|
||||
|
||||
test('canLaunch passes true', () async {
|
||||
final _FakeUrlLauncherApi api = _FakeUrlLauncherApi();
|
||||
final UrlLauncherLinux launcher = UrlLauncherLinux(api: api);
|
||||
|
||||
final bool canLaunch = await launcher.canLaunch('http://example.com/');
|
||||
|
||||
expect(canLaunch, true);
|
||||
});
|
||||
|
||||
test('canLaunch passes false', () async {
|
||||
final _FakeUrlLauncherApi api = _FakeUrlLauncherApi(canLaunch: false);
|
||||
final UrlLauncherLinux launcher = UrlLauncherLinux(api: api);
|
||||
|
||||
final bool canLaunch = await launcher.canLaunch('http://example.com/');
|
||||
|
||||
expect(canLaunch, false);
|
||||
});
|
||||
|
||||
test('launch', () async {
|
||||
final _FakeUrlLauncherApi api = _FakeUrlLauncherApi();
|
||||
final UrlLauncherLinux launcher = UrlLauncherLinux(api: api);
|
||||
const String url = 'http://example.com/';
|
||||
|
||||
final bool launched = await launcher.launch(
|
||||
url,
|
||||
useSafariVC: true,
|
||||
useWebView: false,
|
||||
enableJavaScript: false,
|
||||
enableDomStorage: false,
|
||||
universalLinksOnly: false,
|
||||
headers: const <String, String>{},
|
||||
);
|
||||
|
||||
expect(launched, true);
|
||||
expect(api.argument, url);
|
||||
});
|
||||
|
||||
test('launch should throw if platform returns an error', () async {
|
||||
final _FakeUrlLauncherApi api = _FakeUrlLauncherApi(error: 'An error');
|
||||
final UrlLauncherLinux launcher = UrlLauncherLinux(api: api);
|
||||
|
||||
await expectLater(
|
||||
launcher.launch(
|
||||
'http://example.com/',
|
||||
useSafariVC: true,
|
||||
useWebView: false,
|
||||
enableJavaScript: false,
|
||||
enableDomStorage: false,
|
||||
universalLinksOnly: false,
|
||||
headers: const <String, String>{},
|
||||
),
|
||||
throwsA(isA<PlatformException>()
|
||||
.having((PlatformException e) => e.code, 'code', 'Launch Error')
|
||||
.having((PlatformException e) => e.message, 'message',
|
||||
contains('Failed to launch URL: An error'))));
|
||||
});
|
||||
|
||||
group('launchUrl', () {
|
||||
test('passes URL', () async {
|
||||
final _FakeUrlLauncherApi api = _FakeUrlLauncherApi();
|
||||
final UrlLauncherLinux launcher = UrlLauncherLinux(api: api);
|
||||
const String url = 'http://example.com/';
|
||||
|
||||
final bool launched =
|
||||
await launcher.launchUrl(url, const LaunchOptions());
|
||||
|
||||
expect(launched, true);
|
||||
expect(api.argument, url);
|
||||
});
|
||||
|
||||
test('throws if platform returns an error', () async {
|
||||
final _FakeUrlLauncherApi api = _FakeUrlLauncherApi(error: 'An error');
|
||||
final UrlLauncherLinux launcher = UrlLauncherLinux(api: api);
|
||||
|
||||
await expectLater(
|
||||
launcher.launchUrl('http://example.com/', const LaunchOptions()),
|
||||
throwsA(isA<PlatformException>()
|
||||
.having((PlatformException e) => e.code, 'code', 'Launch Error')
|
||||
.having((PlatformException e) => e.message, 'message',
|
||||
contains('Failed to launch URL: An error'))));
|
||||
});
|
||||
});
|
||||
|
||||
group('supportsMode', () {
|
||||
test('returns true for platformDefault', () async {
|
||||
final UrlLauncherLinux launcher = UrlLauncherLinux();
|
||||
expect(await launcher.supportsMode(PreferredLaunchMode.platformDefault),
|
||||
true);
|
||||
});
|
||||
|
||||
test('returns true for external application', () async {
|
||||
final UrlLauncherLinux launcher = UrlLauncherLinux();
|
||||
expect(
|
||||
await launcher
|
||||
.supportsMode(PreferredLaunchMode.externalApplication),
|
||||
true);
|
||||
});
|
||||
|
||||
test('returns false for other modes', () async {
|
||||
final UrlLauncherLinux launcher = UrlLauncherLinux();
|
||||
expect(
|
||||
await launcher.supportsMode(
|
||||
PreferredLaunchMode.externalNonBrowserApplication),
|
||||
false);
|
||||
expect(
|
||||
await launcher.supportsMode(PreferredLaunchMode.inAppBrowserView),
|
||||
false);
|
||||
expect(await launcher.supportsMode(PreferredLaunchMode.inAppWebView),
|
||||
false);
|
||||
});
|
||||
});
|
||||
|
||||
test('supportsCloseForMode returns false', () async {
|
||||
final UrlLauncherLinux launcher = UrlLauncherLinux();
|
||||
expect(
|
||||
await launcher
|
||||
.supportsCloseForMode(PreferredLaunchMode.platformDefault),
|
||||
false);
|
||||
expect(
|
||||
await launcher
|
||||
.supportsCloseForMode(PreferredLaunchMode.externalApplication),
|
||||
false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class _FakeUrlLauncherApi implements UrlLauncherApi {
|
||||
_FakeUrlLauncherApi({this.canLaunch = true, this.error});
|
||||
|
||||
/// The value to return from canLaunch.
|
||||
final bool canLaunch;
|
||||
|
||||
/// The error to return from launchUrl, if any.
|
||||
final String? error;
|
||||
|
||||
/// The argument that was passed to an API call.
|
||||
String? argument;
|
||||
|
||||
@override
|
||||
Future<bool> canLaunchUrl(String url) async {
|
||||
argument = url;
|
||||
return canLaunch;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> launchUrl(String url) async {
|
||||
argument = url;
|
||||
return error;
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
BinaryMessenger? get pigeonVar_binaryMessenger => null;
|
||||
|
||||
@override
|
||||
// ignore: non_constant_identifier_names
|
||||
String get pigeonVar_messageChannelSuffix => '';
|
||||
}
|
||||
Reference in New Issue
Block a user