Merge branch 'main' into history

This commit is contained in:
Fabian Freund
2025-09-18 14:37:45 +02:00
17 changed files with 108 additions and 315 deletions
+5
View File
@@ -1,3 +1,8 @@
## 0.9.24
### GeckoView 143.0.0
* Upgraded GeckoView
## 0.9.23
### GeckoView 142.0.1
+6 -1
View File
@@ -1,6 +1,7 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "org.jetbrains.kotlin.plugin.compose" version "2.1.20"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}
@@ -49,10 +50,14 @@ android {
dependencies {
// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// implementation 'androidx.glance:glance-appwidget:1.0.0'
implementation 'androidx.glance:glance-appwidget:1.1.1'
implementation 'com.google.android.material:material:1.12.0'
}
buildFeatures {
compose true
}
signingConfigs {
release {
keyAlias System.getenv("KEY_ALIAS")
+14 -22
View File
@@ -62,6 +62,7 @@
<activity
android:name=".MainActivity"
android:label="WebLibre"
android:exported="true"
android:launchMode="singleTask"
android:taskAffinity="eu.weblibre.gecko.task"
@@ -88,7 +89,7 @@
</intent-filter>
<intent-filter>
<action android:name="eu.weblibre.gecko.action.LAUNCH" />
<action android:name="es.antonborri.home_widget.action.LAUNCH" />
</intent-filter>
<intent-filter>
@@ -133,6 +134,12 @@
<data android:mimeType="application/pdf" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PROCESS_TEXT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.WEB_SEARCH" />
@@ -176,32 +183,17 @@
android:label="@string/mozac_feature_addons_addons"
android:theme="@style/Theme.AppCompat.Light"/>
<receiver android:name="FullWidgetProvider" android:exported="true">
<receiver
android:name=".SearchBarWidgetReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/full_widget_info"/>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/search_bar_widget_info" />
</receiver>
<receiver android:name="CompactWidgetProvider" android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/compact_widget_info"/>
</receiver>
<receiver android:name="SearchBarWidgetProvider" android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/search_bar_widget_info"/>
</receiver>
<service
android:name="eu.weblibre.flutter_mozilla_components.services.CustomTabsService"
@@ -1,59 +0,0 @@
/*
* Copyright (c) 2024-2025 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.weblibre.gecko
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.SharedPreferences
import android.graphics.BitmapFactory
import android.net.Uri
import android.view.View
import android.widget.RemoteViews
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
import es.antonborri.home_widget.HomeWidgetLaunchIntent
import es.antonborri.home_widget.HomeWidgetProvider
class CompactWidgetProvider : HomeWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) {
appWidgetIds.forEach { widgetId ->
val views = RemoteViews(context.packageName, R.layout.compact_widget).apply {
val searchIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
Uri.parse("widget://search"))
setOnClickPendingIntent(R.id.search_button, searchIntent)
val assistantIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
Uri.parse("widget://assistant"))
setOnClickPendingIntent(R.id.assistant_button, assistantIntent)
val summarizerIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
Uri.parse("widget://summarizer"))
setOnClickPendingIntent(R.id.summarizer_button, summarizerIntent)
}
appWidgetManager.updateAppWidget(widgetId, views)
}
}
}
@@ -1,59 +0,0 @@
/*
* Copyright (c) 2024-2025 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.weblibre.gecko
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.SharedPreferences
import android.graphics.BitmapFactory
import android.net.Uri
import android.view.View
import android.widget.RemoteViews
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
import es.antonborri.home_widget.HomeWidgetLaunchIntent
import es.antonborri.home_widget.HomeWidgetProvider
class FullWidgetProvider : HomeWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) {
appWidgetIds.forEach { widgetId ->
val views = RemoteViews(context.packageName, R.layout.full_widget).apply {
val searchIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
Uri.parse("widget://search"))
setOnClickPendingIntent(R.id.search_button, searchIntent)
val assistantIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
Uri.parse("widget://assistant"))
setOnClickPendingIntent(R.id.assistant_button, assistantIntent)
val summarizerIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
Uri.parse("widget://summarizer"))
setOnClickPendingIntent(R.id.summarizer_button, summarizerIntent)
}
appWidgetManager.updateAppWidget(widgetId, views)
}
}
}
@@ -1,47 +1,79 @@
/*
* Copyright (c) 2024-2025 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.weblibre.gecko
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.SharedPreferences
import android.graphics.BitmapFactory
import android.net.Uri
import android.view.View
import android.widget.RemoteViews
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.glance.GlanceId
import androidx.glance.GlanceModifier
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.action.clickable
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import androidx.glance.appwidget.provideContent
import androidx.glance.background
import androidx.glance.layout.Alignment
import androidx.glance.layout.Row
import androidx.glance.layout.fillMaxWidth
import androidx.glance.layout.padding
import androidx.glance.layout.wrapContentHeight
import androidx.glance.text.Text
import androidx.glance.text.TextStyle
import androidx.glance.unit.ColorProvider
import es.antonborri.home_widget.HomeWidgetLaunchIntent
import es.antonborri.home_widget.HomeWidgetProvider
import android.net.Uri
import es.antonborri.home_widget.actionStartActivity
import androidx.core.net.toUri
class SearchBarWidgetProvider : HomeWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) {
appWidgetIds.forEach { widgetId ->
val views = RemoteViews(context.packageName, R.layout.search_bar_widget).apply {
val searchIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
Uri.parse("widget://search"))
setOnClickPendingIntent(R.id.search_button, searchIntent)
}
class SearchBarGlanceWidget : GlanceAppWidget() {
appWidgetManager.updateAppWidget(widgetId, views)
override suspend fun provideGlance(context: Context, id: GlanceId) {
provideContent {
SearchBarContent(context)
}
}
}
}
@Composable
private fun SearchBarContent(context: Context) {
Row(
modifier = GlanceModifier
.fillMaxWidth()
.wrapContentHeight()
.background(ImageProvider(R.drawable.search_text_field))
.padding(12.dp)
.clickable(onClick = actionStartActivity<MainActivity>(context,
"widget://search".toUri())),
verticalAlignment = Alignment.CenterVertically
) {
// Start icon
Image(
provider = ImageProvider(R.drawable.icon_with_size),
contentDescription = "Search icon",
modifier = GlanceModifier.padding(end = 8.dp)
)
// Search text
Text(
text = "Search with WebLibre...",
style = TextStyle(
color = ColorProvider(Color(0xFF848388)),
fontSize = 16.sp
),
modifier = GlanceModifier.defaultWeight()
)
// End icon (microphone)
Image(
provider = ImageProvider(R.drawable.mdi_icon_microphone_tint),
contentDescription = "Microphone icon",
modifier = GlanceModifier.padding(start = 8.dp)
)
}
}
class SearchBarWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = SearchBarGlanceWidget()
}
@@ -1,45 +0,0 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Widget.WebLibreWidget.AppWidget.Container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:theme="@style/Theme.WebLibreWidget.AppWidgetContainer"
android:gravity="center_vertical">
<Button
android:id="@+id/search_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/search_text_field"
android:drawableStart="@drawable/icon_with_size"
android:drawableEnd="@drawable/mdi_icon_microphone_tint"
android:drawablePadding="8dp"
android:gravity="start|center_vertical"
android:padding="12dp"
android:text="Search with Kagi..."
android:textColor="#848388" />
<Button
android:id="@+id/summarizer_button"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginStart="8dp"
android:backgroundTint="#333237"
android:background="@drawable/button"
android:drawableTint="@color/white"
android:drawableStart="@drawable/mdi_icon_text"
android:padding="16dp" />
<Button
android:id="@+id/assistant_button"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginStart="8dp"
android:backgroundTint="#333237"
android:background="@drawable/button"
android:drawableTint="@color/white"
android:drawableStart="@drawable/mdi_icon_brain"
android:padding="16dp" />
</LinearLayout>
@@ -1,55 +0,0 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Widget.WebLibreWidget.AppWidget.Container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp"
android:theme="@style/Theme.WebLibreWidget.AppWidgetContainer">
<Button
android:id="@+id/search_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/search_text_field"
android:text="Search with Kagi..."
android:textColor="#848388"
android:drawablePadding="8dp"
android:padding="12dp"
android:drawableStart="@drawable/icon_with_size"
android:drawableEnd="@drawable/mdi_icon_microphone_tint"
android:gravity="start|center_vertical" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:paddingTop="12dp">
<Button
android:layout_marginStart="8dp"
android:id="@+id/summarizer_button"
android:padding="16dp"
android:backgroundTint="#333237"
android:background="@drawable/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTint="@color/white"
android:drawableStart="@drawable/mdi_icon_text"
android:drawablePadding="8dp"
android:text="Summarizer" />
<Button
android:layout_marginEnd="8dp"
android:id="@+id/assistant_button"
android:padding="16dp"
android:backgroundTint="#333237"
android:background="@drawable/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTint="@color/white"
android:drawableStart="@drawable/mdi_icon_brain"
android:drawablePadding="8dp"
android:text="Assistant" />
</LinearLayout>
</LinearLayout>
@@ -1,13 +0,0 @@
<Button
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/search_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/search_text_field"
android:text="Search with Kagi..."
android:textColor="#848388"
android:drawablePadding="8dp"
android:padding="12dp"
android:drawableStart="@drawable/icon_with_size"
android:drawableEnd="@drawable/mdi_icon_microphone_tint"
android:gravity="start|center_vertical" />
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/compact_widget"
android:resizeMode="none"
android:previewLayout="@layout/compact_widget"
android:targetCellWidth="5"
android:targetCellHeight="1"
android:widgetCategory="home_screen" />
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/full_widget"
android:resizeMode="none"
android:previewLayout="@layout/full_widget"
android:targetCellWidth="5"
android:targetCellHeight="2"
android:widgetCategory="home_screen" />
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/search_bar_widget"
android:initialLayout="@layout/glance_default_loading_layout"
android:resizeMode="none"
android:previewLayout="@layout/search_bar_widget"
android:targetCellWidth="5"
android:targetCellHeight="1"
android:widgetCategory="home_screen" />
android:widgetCategory="home_screen" />
@@ -22,6 +22,7 @@ import 'dart:async';
import 'package:nullability/nullability.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:rxdart/rxdart.dart';
import 'package:weblibre/core/routing/routes.dart';
import 'package:weblibre/data/models/received_intent_parameter.dart';
import 'package:weblibre/features/app_widget/domain/services/home_widget.dart';
import 'package:weblibre/features/geckoview/domain/providers.dart';
@@ -39,6 +40,8 @@ final _contentParserTransformer =
if (parsed != null) {
sink.add(parsed);
} else if (parameter.tool == 'search') {
sink.add(SharedText(SearchRoute.emptySearchText));
}
},
);
@@ -35,6 +35,8 @@ final _sharingIntentTransformer =
StreamTransformer<Intent, ReceivedIntentParameter>.fromHandlers(
handleData: (intent, sink) async {
final data = switch (intent.action) {
'android.intent.action.PROCESS_TEXT' =>
intent.extra['android.intent.extra.PROCESS_TEXT'] as String?,
'android.intent.action.WEB_SEARCH' =>
intent.extra['query'] as String?,
'android.intent.action.VIEW' => intent.data,
+1 -1
View File
@@ -101,7 +101,7 @@ class MainApp extends HookConsumerWidget {
searchText: sharedContent.text,
$extra: true, //launched from intent
);
await router.push(route.location);
await router.push(route.location, extra: route.$extra);
}
}
});
+1 -2
View File
@@ -2,7 +2,7 @@ name: weblibre
description: "The Privacy-Focused & AI-Powered Research Browser"
publish_to: 'none'
resolution: workspace
version: 0.9.23+27
version: 0.9.24+28
environment:
sdk: '>=3.8.0 <4.0.0'
@@ -91,7 +91,6 @@ dependency_overrides:
url_launcher_android: 6.3.17
dev_dependencies:
analyzer_plugin: ^0.13.4
build_runner: ^2.4.15
copy_with_extension_gen: ^6.0.1
custom_lint: ^0.7.6
+3
View File
@@ -0,0 +1,3 @@
GeckoView 143.0.0
* Upgraded GeckoView