Rename mobile app to Buzz (#955)
Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"SPROUT_RELAY_URL": "http://localhost:3000",
|
||||
"SPROUT_DEV_PUBKEY": "<your-hex-pubkey-here>"
|
||||
"BUZZ_RELAY_URL": "http://localhost:3000",
|
||||
"BUZZ_DEV_PUBKEY": "<your-hex-pubkey-here>"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Sprout Mobile
|
||||
# Buzz Mobile
|
||||
|
||||
Flutter mobile client for Sprout.
|
||||
Flutter mobile client for Buzz.
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.sprout.sprout_mobile"
|
||||
namespace = "com.buzz.buzz_mobile"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
@@ -21,7 +21,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.sprout.sprout_mobile"
|
||||
applicationId = "com.buzz.buzz_mobile"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<application
|
||||
android:label="Sprout"
|
||||
android:label="Buzz"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sprout.sprout_mobile
|
||||
package com.buzz.buzz_mobile
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
@@ -222,7 +222,7 @@ class MainActivity : FlutterActivity() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MEDIA_UPLOAD_CHANNEL = "sprout/media_upload"
|
||||
private const val MEDIA_UPLOAD_CHANNEL = "buzz/media_upload"
|
||||
private const val SANITIZE_IMAGE_FOR_UPLOAD_METHOD = "sanitizeImageForUpload"
|
||||
private const val TRANSCODE_IMAGE_TO_JPEG_METHOD = "transcodeImageToJpeg"
|
||||
private const val TRANSCODE_VIDEO_TO_MP4_METHOD = "transcodeVideoToMp4"
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 301 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 488 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 62 KiB |
@@ -5,5 +5,5 @@
|
||||
// without patching tracked files by writing
|
||||
// `mobile/ios/Flutter/AppOverrides.xcconfig` containing
|
||||
// `BUNDLE_IDENTIFIER = your.app.id` (gitignored).
|
||||
BUNDLE_IDENTIFIER = com.sprout.sproutMobile
|
||||
BUNDLE_IDENTIFIER = com.buzz.buzzMobile
|
||||
#include? "AppOverrides.xcconfig"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// Defaults for the iOS Release build. Internal/custom builds (e.g. an
|
||||
// enterprise-signed distribution) override these without patching tracked
|
||||
// files by writing `mobile/ios/Flutter/AppOverrides.xcconfig` (gitignored).
|
||||
BUNDLE_IDENTIFIER = com.sprout.sproutMobile
|
||||
BUNDLE_IDENTIFIER = com.buzz.buzzMobile
|
||||
CODE_SIGN_STYLE = Automatic
|
||||
CODE_SIGN_IDENTITY = iPhone Developer
|
||||
#include? "AppOverrides.xcconfig"
|
||||
|
||||
@@ -483,7 +483,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = Sprout;
|
||||
PRODUCT_NAME = Buzz;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
@@ -504,7 +504,7 @@
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sprout.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Sprout";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Buzz.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Buzz";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -520,7 +520,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER).RunnerTests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sprout.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Sprout";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Buzz.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Buzz";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -536,7 +536,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER).RunnerTests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sprout.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Sprout";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Buzz.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Buzz";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
@@ -665,7 +665,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = Sprout;
|
||||
PRODUCT_NAME = Buzz;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -688,7 +688,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = Sprout;
|
||||
PRODUCT_NAME = Buzz;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
||||
@@ -18,7 +18,7 @@ import UserNotifications
|
||||
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
||||
mediaUploadChannel = FlutterMethodChannel(
|
||||
name: "sprout/media_upload",
|
||||
name: "buzz/media_upload",
|
||||
binaryMessenger: engineBridge.applicationRegistrar.messenger()
|
||||
)
|
||||
mediaUploadChannel?.setMethodCallHandler { [weak self] call, result in
|
||||
|
||||
|
Before Width: | Height: | Size: 333 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 442 KiB After Width: | Height: | Size: 22 KiB |
@@ -7,7 +7,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Sprout</string>
|
||||
<string>Buzz</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Sprout</string>
|
||||
<string>Buzz</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
@@ -27,9 +27,9 @@
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Sprout needs camera access to scan QR codes for device pairing.</string>
|
||||
<string>Buzz needs camera access to scan QR codes for device pairing.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Sprout needs photo library access so you can attach images to messages.</string>
|
||||
<string>Buzz needs photo library access so you can attach images to messages.</string>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
|
||||
@@ -59,7 +59,7 @@ class App extends HookConsumerWidget {
|
||||
});
|
||||
|
||||
return MaterialApp(
|
||||
title: 'Sprout',
|
||||
title: 'Buzz',
|
||||
theme: AppTheme.light(colorScheme: lightScheme),
|
||||
darkTheme: AppTheme.dark(colorScheme: darkScheme),
|
||||
themeMode: effectiveMode,
|
||||
|
||||
@@ -127,7 +127,7 @@ class ToolItem extends TranscriptItem {
|
||||
final String id;
|
||||
String title;
|
||||
String toolName;
|
||||
String? sproutToolName;
|
||||
String? buzzToolName;
|
||||
ToolStatus status;
|
||||
Map<String, dynamic> args;
|
||||
String result;
|
||||
@@ -139,7 +139,7 @@ class ToolItem extends TranscriptItem {
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.toolName,
|
||||
this.sproutToolName,
|
||||
this.buzzToolName,
|
||||
required this.status,
|
||||
required this.args,
|
||||
required this.result,
|
||||
|
||||
@@ -3,10 +3,10 @@ import 'dart:convert';
|
||||
import 'observer_models.dart';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sprout tool catalogs
|
||||
// Buzz tool catalogs
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const _sproutReadTools = <String>{
|
||||
const _buzzReadTools = <String>{
|
||||
'get_messages',
|
||||
'get_channel_history',
|
||||
'get_thread',
|
||||
@@ -27,7 +27,7 @@ const _sproutReadTools = <String>{
|
||||
'get_contact_list',
|
||||
};
|
||||
|
||||
const _sproutWriteTools = <String>{
|
||||
const _buzzWriteTools = <String>{
|
||||
'send_message',
|
||||
'send_diff_message',
|
||||
'edit_message',
|
||||
@@ -61,12 +61,12 @@ const _sproutWriteTools = <String>{
|
||||
'set_contact_list',
|
||||
};
|
||||
|
||||
final _sproutToolNames = <String>{..._sproutReadTools, ..._sproutWriteTools};
|
||||
final _buzzToolNames = <String>{..._buzzReadTools, ..._buzzWriteTools};
|
||||
|
||||
final _sproutToolNamesByLength = _sproutToolNames.toList()
|
||||
final _buzzToolNamesByLength = _buzzToolNames.toList()
|
||||
..sort((a, b) => b.length.compareTo(a.length));
|
||||
|
||||
final _sproutToolTitleAliases = <(RegExp, String)>[
|
||||
final _buzzToolTitleAliases = <(RegExp, String)>[
|
||||
(RegExp(r'\bsending message to channel\b'), 'send_message'),
|
||||
(RegExp(r'\bretrieving recent messages from channel\b'), 'get_messages'),
|
||||
(RegExp(r'\bgetting channel details\b'), 'get_channel'),
|
||||
@@ -119,12 +119,12 @@ String _normalizeToolNameText(String value) {
|
||||
.replaceAll(RegExp(r'^_+|_+$'), '');
|
||||
}
|
||||
|
||||
String? _findSproutToolName(String value, bool includeShortNames) {
|
||||
final alias = _findSproutToolAlias(value);
|
||||
String? _findBuzzToolName(String value, bool includeShortNames) {
|
||||
final alias = _findBuzzToolAlias(value);
|
||||
if (alias != null) return alias;
|
||||
|
||||
final normalized = _normalizeToolNameText(value);
|
||||
for (final name in _sproutToolNamesByLength) {
|
||||
for (final name in _buzzToolNamesByLength) {
|
||||
if ((!includeShortNames && name.length < 8) || !normalized.contains(name)) {
|
||||
continue;
|
||||
}
|
||||
@@ -133,13 +133,13 @@ String? _findSproutToolName(String value, bool includeShortNames) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String? _findSproutToolAlias(String value) {
|
||||
String? _findBuzzToolAlias(String value) {
|
||||
final normalizedPhrase = value
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replaceAll(RegExp(r'[_-]+'), ' ')
|
||||
.replaceAll(RegExp(r'\s+'), ' ');
|
||||
for (final (pattern, name) in _sproutToolTitleAliases) {
|
||||
for (final (pattern, name) in _buzzToolTitleAliases) {
|
||||
if (pattern.hasMatch(normalizedPhrase)) return name;
|
||||
}
|
||||
return null;
|
||||
@@ -159,12 +159,12 @@ bool _isGenericToolTitle(String value) {
|
||||
}
|
||||
|
||||
String _normalizeToolName(String title) {
|
||||
final knownName = _findSproutToolName(title, true);
|
||||
final knownName = _findBuzzToolName(title, true);
|
||||
if (knownName != null) return knownName;
|
||||
|
||||
final normalized = _normalizeToolNameText(
|
||||
title,
|
||||
).replaceAll(RegExp(r'^sprout_'), '');
|
||||
).replaceAll(RegExp(r'^buzz_'), '');
|
||||
return RegExp(r'[a-z][a-z0-9_]+').firstMatch(normalized)?[0] ?? normalized;
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ _parsePromptText(String text) {
|
||||
|
||||
PromptSection? eventSection;
|
||||
for (final section in sections) {
|
||||
if (section.title.toLowerCase().startsWith('sprout event')) {
|
||||
if (section.title.toLowerCase().startsWith('buzz event')) {
|
||||
eventSection = section;
|
||||
break;
|
||||
}
|
||||
@@ -250,7 +250,7 @@ _parsePromptText(String text) {
|
||||
userText: eventContent,
|
||||
userTitle: eventKind != null && eventKind.isNotEmpty
|
||||
? _titleCase(eventKind)
|
||||
: 'Sprout event',
|
||||
: 'Buzz event',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -324,16 +324,16 @@ Map<String, dynamic> _extractToolArgs(Map<String, dynamic> update) {
|
||||
return const {};
|
||||
}
|
||||
|
||||
({String title, String toolName, String? sproutToolName}) _extractToolIdentity(
|
||||
({String title, String toolName, String? buzzToolName}) _extractToolIdentity(
|
||||
Map<String, dynamic> update,
|
||||
) {
|
||||
final candidates = _collectToolNameCandidates(update);
|
||||
String? knownName;
|
||||
for (final c in candidates) {
|
||||
knownName = _findSproutToolName(c, true);
|
||||
knownName = _findBuzzToolName(c, true);
|
||||
if (knownName != null) break;
|
||||
}
|
||||
knownName ??= _findSproutToolName(_safeJsonEncode(update), false);
|
||||
knownName ??= _findBuzzToolName(_safeJsonEncode(update), false);
|
||||
String? firstSpecific;
|
||||
for (final candidate in candidates) {
|
||||
if (!_isGenericToolTitle(candidate)) {
|
||||
@@ -346,7 +346,7 @@ Map<String, dynamic> _extractToolArgs(Map<String, dynamic> update) {
|
||||
return (
|
||||
title: title,
|
||||
toolName: knownName ?? _normalizeToolName(firstSpecific ?? title),
|
||||
sproutToolName: knownName,
|
||||
buzzToolName: knownName,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -529,7 +529,7 @@ List<TranscriptItem> buildTranscript(List<ObserverFrame> events) {
|
||||
String id,
|
||||
String title,
|
||||
String toolName,
|
||||
String? sproutToolName,
|
||||
String? buzzToolName,
|
||||
ToolStatus status,
|
||||
Map<String, dynamic> args,
|
||||
String result,
|
||||
@@ -537,16 +537,16 @@ List<TranscriptItem> buildTranscript(List<ObserverFrame> events) {
|
||||
String timestamp,
|
||||
) {
|
||||
final existing = itemsById[id];
|
||||
final canonicalSproutToolName =
|
||||
sproutToolName ?? _findSproutToolName(toolName, true);
|
||||
final canonicalBuzzToolName =
|
||||
buzzToolName ?? _findBuzzToolName(toolName, true);
|
||||
if (existing is ToolItem) {
|
||||
if (!_isGenericToolTitle(title)) {
|
||||
existing.title = title;
|
||||
}
|
||||
if (canonicalSproutToolName != null) {
|
||||
existing.sproutToolName = canonicalSproutToolName;
|
||||
existing.toolName = canonicalSproutToolName;
|
||||
} else if (existing.sproutToolName == null &&
|
||||
if (canonicalBuzzToolName != null) {
|
||||
existing.buzzToolName = canonicalBuzzToolName;
|
||||
existing.toolName = canonicalBuzzToolName;
|
||||
} else if (existing.buzzToolName == null &&
|
||||
!_isGenericToolTitle(toolName)) {
|
||||
existing.toolName = toolName;
|
||||
}
|
||||
@@ -560,8 +560,8 @@ List<TranscriptItem> buildTranscript(List<ObserverFrame> events) {
|
||||
final item = ToolItem(
|
||||
id: id,
|
||||
title: title,
|
||||
toolName: canonicalSproutToolName ?? toolName,
|
||||
sproutToolName: canonicalSproutToolName,
|
||||
toolName: canonicalBuzzToolName ?? toolName,
|
||||
buzzToolName: canonicalBuzzToolName,
|
||||
status: status,
|
||||
args: args,
|
||||
result: result,
|
||||
@@ -688,7 +688,7 @@ List<TranscriptItem> buildTranscript(List<ObserverFrame> events) {
|
||||
'tool:$toolId',
|
||||
identity.title,
|
||||
identity.toolName,
|
||||
identity.sproutToolName,
|
||||
identity.buzzToolName,
|
||||
_normalizeToolStatus(_asString(update['status']) ?? 'executing'),
|
||||
_extractToolArgs(update),
|
||||
_extractToolResult(update),
|
||||
@@ -708,7 +708,7 @@ List<TranscriptItem> buildTranscript(List<ObserverFrame> events) {
|
||||
'tool:$toolId',
|
||||
identity.title,
|
||||
identity.toolName,
|
||||
identity.sproutToolName,
|
||||
identity.buzzToolName,
|
||||
status,
|
||||
_extractToolArgs(update),
|
||||
_extractToolResult(update),
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
String channelMutesKey(String pubkey) => 'sprout.channel-mutes.v1:$pubkey';
|
||||
String channelMutesKey(String pubkey) => 'buzz.channel-mutes.v1:$pubkey';
|
||||
|
||||
class ChannelMuteEntry {
|
||||
final bool muted;
|
||||
|
||||
@@ -2,8 +2,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
String channelSectionsKey(String pubkey) =>
|
||||
'sprout.channel-sections.v1:$pubkey';
|
||||
String channelSectionsKey(String pubkey) => 'buzz.channel-sections.v1:$pubkey';
|
||||
|
||||
class ChannelSection {
|
||||
final String id;
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
String channelStarsKey(String pubkey) => 'sprout.channel-stars.v1:$pubkey';
|
||||
String channelStarsKey(String pubkey) => 'buzz.channel-stars.v1:$pubkey';
|
||||
|
||||
class ChannelStarEntry {
|
||||
final bool starred;
|
||||
|
||||
@@ -159,7 +159,7 @@ const emojiCategories = <({String label, IconData icon, List<String> emoji})>[
|
||||
),
|
||||
(
|
||||
label: 'Nature',
|
||||
icon: LucideIcons.sprout,
|
||||
icon: LucideIcons.leaf,
|
||||
emoji: [
|
||||
'\u{1F331}',
|
||||
'\u{1F332}',
|
||||
|
||||
@@ -8,18 +8,17 @@ import 'package:uuid/uuid.dart';
|
||||
import 'read_state_format.dart';
|
||||
import 'read_state_time.dart';
|
||||
|
||||
const _clientIdKeyPrefix = 'sprout.nip-rs.client-id';
|
||||
const _slotIdKeyPrefix = 'sprout.nip-rs.slot-id';
|
||||
const _clientIdKeyPrefix = 'buzz.nip-rs.client-id';
|
||||
const _slotIdKeyPrefix = 'buzz.nip-rs.slot-id';
|
||||
const _uuid = Uuid();
|
||||
|
||||
String localReadStateKey(String pubkey) =>
|
||||
'sprout.channel-read-state.v2:$pubkey';
|
||||
String localReadStateKey(String pubkey) => 'buzz.channel-read-state.v2:$pubkey';
|
||||
|
||||
String localPublishableContextKey(String pubkey) =>
|
||||
'sprout.channel-read-state.publishable.v1:$pubkey';
|
||||
'buzz.channel-read-state.publishable.v1:$pubkey';
|
||||
|
||||
String localSourceCreatedAtKey(String pubkey) =>
|
||||
'sprout.channel-read-state.source-created-at.v1:$pubkey';
|
||||
'buzz.channel-read-state.source-created-at.v1:$pubkey';
|
||||
|
||||
String clientIdKey(String pubkey) => '$_clientIdKeyPrefix:$pubkey';
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ List<TimelineMessage> formatTimeline(
|
||||
String? currentPubkey,
|
||||
}) {
|
||||
// 1. Collect deletion targets. Both kind:5 (NIP-09) and kind:9005
|
||||
// (Sprout-native) are deletion markers; mirror desktop's behavior.
|
||||
// (Buzz-native) are deletion markers; mirror desktop's behavior.
|
||||
final deletedIds = <String>{};
|
||||
for (final event in events) {
|
||||
if (event.kind != EventKind.deletion &&
|
||||
|
||||
@@ -29,7 +29,7 @@ class CustomEmoji {
|
||||
const int kindEmojiSet = 30030;
|
||||
|
||||
/// d-tag for a member's own custom emoji set.
|
||||
const String customEmojiSetDTag = 'sprout:custom-emoji';
|
||||
const String customEmojiSetDTag = 'buzz:custom-emoji';
|
||||
|
||||
final RegExp _shortcodeRe = RegExp(r'^[a-z0-9_-]+$');
|
||||
|
||||
|
||||
@@ -67,13 +67,13 @@ class PairingPage extends HookConsumerWidget {
|
||||
|
||||
// Branding
|
||||
Icon(
|
||||
LucideIcons.sprout,
|
||||
LucideIcons.hexagon,
|
||||
size: 64,
|
||||
color: context.colors.primary,
|
||||
),
|
||||
const SizedBox(height: Grid.xs),
|
||||
Text(
|
||||
'Welcome to Sprout',
|
||||
'Welcome to Buzz',
|
||||
style: context.textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: Grid.xxs),
|
||||
@@ -123,7 +123,7 @@ class PairingPage extends HookConsumerWidget {
|
||||
TextField(
|
||||
controller: codeController,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'nostrpair://... or sprout://...',
|
||||
hintText: 'nostrpair://... or buzz://...',
|
||||
prefixIcon: Icon(LucideIcons.link),
|
||||
isDense: true,
|
||||
),
|
||||
@@ -284,7 +284,7 @@ class _SasVerificationView extends StatelessWidget {
|
||||
const SizedBox(height: Grid.lg),
|
||||
|
||||
Text(
|
||||
'You are about to transfer your Sprout identity\nto this device. Only confirm if you initiated\nthis pairing from your desktop.',
|
||||
'You are about to transfer your Buzz identity\nto this device. Only confirm if you initiated\nthis pairing from your desktop.',
|
||||
textAlign: TextAlign.center,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: context.colors.onSurfaceVariant,
|
||||
|
||||
@@ -75,7 +75,7 @@ class PairingNotifier extends Notifier<PairingState> {
|
||||
if (trimmed.startsWith('nostrpair://')) {
|
||||
return _pairNipAb(trimmed);
|
||||
}
|
||||
// Legacy sprout:// flow.
|
||||
// Legacy buzz:// flow.
|
||||
return _pairLegacy(trimmed);
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ class PairingNotifier extends Notifier<PairingState> {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Legacy sprout:// flow ───────────────────────────────────────────────
|
||||
// ── Legacy buzz:// flow ───────────────────────────────────────────────
|
||||
|
||||
Future<void> _pairLegacy(String rawInput) async {
|
||||
state = const PairingState(status: PairingStatus.connecting);
|
||||
@@ -593,8 +593,8 @@ class PairingNotifier extends Notifier<PairingState> {
|
||||
Workspace _parseLegacyInput(String raw) {
|
||||
var payload = raw.trim();
|
||||
|
||||
if (payload.startsWith('sprout://')) {
|
||||
payload = payload.substring('sprout://'.length);
|
||||
if (payload.startsWith('buzz://')) {
|
||||
payload = payload.substring('buzz://'.length);
|
||||
}
|
||||
|
||||
final normalized = base64Url.normalize(payload);
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'package:pointycastle/digests/sha256.dart';
|
||||
import 'relay_provider.dart';
|
||||
|
||||
const _mediaUploadPath = '/media/upload';
|
||||
const _mediaUploadPlatformChannelName = 'sprout/media_upload';
|
||||
const _mediaUploadPlatformChannelName = 'buzz/media_upload';
|
||||
const _sanitizeImageForUploadMethod = 'sanitizeImageForUpload';
|
||||
const _transcodeVideoToMp4Method = 'transcodeVideoToMp4';
|
||||
const _transcodeImageToJpegMethod = 'transcodeImageToJpeg';
|
||||
@@ -298,7 +298,7 @@ class MediaUploadService {
|
||||
|
||||
return nostr.Event.from(
|
||||
kind: _uploadAuthKind,
|
||||
content: 'Upload sprout-media',
|
||||
content: 'Upload buzz-media',
|
||||
tags: tags,
|
||||
secretKey: privkeyHex,
|
||||
verify: false,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'nostr_models.dart';
|
||||
|
||||
/// Canonical [NostrFilter] constructors for common Sprout queries.
|
||||
/// Canonical [NostrFilter] constructors for common Buzz queries.
|
||||
///
|
||||
/// Centralising filter shapes keeps relay queries consistent across providers
|
||||
/// and makes kind/tag conventions easy to audit.
|
||||
|
||||
@@ -38,7 +38,7 @@ abstract final class EventKind {
|
||||
static const channelEventKinds = [
|
||||
deletion, // 5
|
||||
reaction, // 7
|
||||
nip29DeleteEvent, // 9005 — Sprout-native deletion
|
||||
nip29DeleteEvent, // 9005 — Buzz-native deletion
|
||||
...channelMessageEventKinds,
|
||||
40001, // legacy pre-migration stream messages
|
||||
streamMessageEdit, // 40003
|
||||
@@ -337,7 +337,7 @@ List<MemberEntry> membersFromEvent(NostrEvent event) {
|
||||
];
|
||||
}
|
||||
|
||||
/// Parse a Sprout command response from the relay's OK message content.
|
||||
/// Parse a Buzz command response from the relay's OK message content.
|
||||
///
|
||||
/// Command kinds (e.g. 41010, 30620, 46020) return `"response:{...}"` in the
|
||||
/// OK message. Returns `null` if the message is not a command response or the
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
/// Lightweight HTTP context for talking to the Sprout relay.
|
||||
/// Lightweight HTTP context for talking to the Buzz relay.
|
||||
///
|
||||
/// In the pure-nostr architecture, all data flow happens over the relay
|
||||
/// WebSocket. This client now exists only to provide a base URL (and a
|
||||
|
||||
@@ -28,12 +28,12 @@ class RelayConfig {
|
||||
/// Compile-time environment config via --dart-define.
|
||||
///
|
||||
/// Run with:
|
||||
/// flutter run --dart-define=SPROUT_RELAY_URL=http://localhost:3000
|
||||
/// flutter run --dart-define=BUZZ_RELAY_URL=http://localhost:3000
|
||||
///
|
||||
/// Or create a `.env.json` and use --dart-define-from-file=.env.json
|
||||
class Env {
|
||||
static const relayUrl = String.fromEnvironment(
|
||||
'SPROUT_RELAY_URL',
|
||||
'BUZZ_RELAY_URL',
|
||||
defaultValue: 'http://localhost:3000',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Accent colors matching the desktop Sprout app.
|
||||
/// Accent colors matching the desktop Buzz app.
|
||||
class AccentColor {
|
||||
final String name;
|
||||
final Color light;
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'accent_colors.dart';
|
||||
|
||||
// Catppuccin Latte (mauve accent) — matches Sprout desktop light theme
|
||||
// Catppuccin Latte (mauve accent) — matches Buzz desktop light theme
|
||||
const lightColorScheme = ColorScheme(
|
||||
brightness: Brightness.light,
|
||||
primary: Color(0xFF8839EF), // Latte Mauve
|
||||
@@ -35,7 +35,7 @@ const lightColorScheme = ColorScheme(
|
||||
surfaceContainerHighest: Color(0xFFFFFFFF),
|
||||
);
|
||||
|
||||
// Catppuccin Macchiato (mauve accent) — matches Sprout desktop dark theme
|
||||
// Catppuccin Macchiato (mauve accent) — matches Buzz desktop dark theme
|
||||
const darkColorScheme = ColorScheme(
|
||||
brightness: Brightness.dark,
|
||||
primary: Color(0xFFA875F5), // Macchiato Mauve (saturated)
|
||||
|
||||
@@ -7,9 +7,9 @@ import 'adaptive_theme.dart';
|
||||
import 'color_scheme.dart';
|
||||
import 'theme_catalog.dart';
|
||||
|
||||
const _themeModeKey = 'sprout_theme_mode';
|
||||
const _accentKey = 'sprout_accent_color';
|
||||
const _schemeKey = 'sprout_color_scheme';
|
||||
const _themeModeKey = 'buzz_theme_mode';
|
||||
const _accentKey = 'buzz_accent_color';
|
||||
const _schemeKey = 'buzz_color_scheme';
|
||||
|
||||
/// Pre-loaded SharedPreferences instance, overridden in main().
|
||||
final savedPrefsProvider = Provider<SharedPreferences>(
|
||||
|
||||
@@ -5,14 +5,14 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'workspace.dart';
|
||||
|
||||
class WorkspaceStorage {
|
||||
static const _keyWorkspaces = 'sprout_workspaces';
|
||||
static const _keyActiveId = 'sprout_active_workspace_id';
|
||||
static const _keyWorkspaces = 'buzz_workspaces';
|
||||
static const _keyActiveId = 'buzz_active_workspace_id';
|
||||
|
||||
// Legacy keys for migration.
|
||||
static const _legacyRelayUrl = 'sprout_relay_url';
|
||||
static const _legacyToken = 'sprout_token';
|
||||
static const _legacyPubkey = 'sprout_pubkey';
|
||||
static const _legacyNsec = 'sprout_nsec';
|
||||
static const _legacyRelayUrl = 'buzz_relay_url';
|
||||
static const _legacyToken = 'buzz_token';
|
||||
static const _legacyPubkey = 'buzz_pubkey';
|
||||
static const _legacyNsec = 'buzz_nsec';
|
||||
|
||||
final FlutterSecureStorage _secure;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: sprout_mobile
|
||||
description: Sprout mobile client
|
||||
name: buzz
|
||||
description: Buzz mobile client
|
||||
publish_to: 'none'
|
||||
version: 0.3.16+1
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:hooks_riverpod/misc.dart';
|
||||
import 'package:sprout_mobile/features/activity/activity_page.dart';
|
||||
import 'package:sprout_mobile/features/activity/activity_provider.dart';
|
||||
import 'package:sprout_mobile/features/activity/feed_item.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel.dart';
|
||||
import 'package:sprout_mobile/features/channels/channels_provider.dart';
|
||||
import 'package:sprout_mobile/features/profile/user_cache_provider.dart';
|
||||
import 'package:sprout_mobile/features/profile/user_profile.dart';
|
||||
import 'package:sprout_mobile/shared/theme/theme.dart';
|
||||
import 'package:buzz/features/activity/activity_page.dart';
|
||||
import 'package:buzz/features/activity/activity_provider.dart';
|
||||
import 'package:buzz/features/activity/feed_item.dart';
|
||||
import 'package:buzz/features/channels/channel.dart';
|
||||
import 'package:buzz/features/channels/channels_provider.dart';
|
||||
import 'package:buzz/features/profile/user_cache_provider.dart';
|
||||
import 'package:buzz/features/profile/user_profile.dart';
|
||||
import 'package:buzz/shared/theme/theme.dart';
|
||||
|
||||
void main() {
|
||||
Widget buildTestable({required List<Override> overrides}) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/activity/feed_item.dart';
|
||||
import 'package:buzz/features/activity/feed_item.dart';
|
||||
|
||||
void main() {
|
||||
group('FeedItem.fromJson', () {
|
||||
|
||||
@@ -4,10 +4,10 @@ import 'dart:convert';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:nostr/nostr.dart' as nostr;
|
||||
import 'package:sprout_mobile/features/channels/agent_activity/observer_models.dart';
|
||||
import 'package:sprout_mobile/features/channels/agent_activity/observer_subscription.dart';
|
||||
import 'package:sprout_mobile/shared/crypto/nip44.dart';
|
||||
import 'package:sprout_mobile/shared/relay/relay.dart';
|
||||
import 'package:buzz/features/channels/agent_activity/observer_models.dart';
|
||||
import 'package:buzz/features/channels/agent_activity/observer_subscription.dart';
|
||||
import 'package:buzz/shared/crypto/nip44.dart';
|
||||
import 'package:buzz/shared/relay/relay.dart';
|
||||
|
||||
void main() {
|
||||
test('provider initializes without circular dependency error', () {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/channels/agent_activity/observer_models.dart';
|
||||
import 'package:sprout_mobile/features/channels/agent_activity/transcript_builder.dart';
|
||||
import 'package:buzz/features/channels/agent_activity/observer_models.dart';
|
||||
import 'package:buzz/features/channels/agent_activity/transcript_builder.dart';
|
||||
|
||||
void main() {
|
||||
test('aggregates assistant chunks until another item seals the message', () {
|
||||
@@ -54,7 +54,7 @@ void main() {
|
||||
expect((items[2] as MessageItem).text, 'Done');
|
||||
});
|
||||
|
||||
test('normalizes sprout tool calls and applies result updates', () {
|
||||
test('normalizes buzz tool calls and applies result updates', () {
|
||||
final items = buildTranscript([
|
||||
_updateFrame(
|
||||
seq: 1,
|
||||
@@ -82,14 +82,14 @@ void main() {
|
||||
expect(items, hasLength(1));
|
||||
expect(items.single, isA<ToolItem>());
|
||||
final tool = items.single as ToolItem;
|
||||
expect(tool.sproutToolName, 'send_message');
|
||||
expect(tool.buzzToolName, 'send_message');
|
||||
expect(tool.toolName, 'send_message');
|
||||
expect(tool.status, ToolStatus.completed);
|
||||
expect(tool.args, {'content': 'hi'});
|
||||
expect(tool.result, 'posted #activity-test-channel');
|
||||
});
|
||||
|
||||
test('parses sprout prompt text into user message and metadata', () {
|
||||
test('parses buzz prompt text into user message and metadata', () {
|
||||
final items = buildTranscript([
|
||||
ObserverFrame(
|
||||
seq: 1,
|
||||
@@ -102,7 +102,7 @@ void main() {
|
||||
'prompt': [
|
||||
{
|
||||
'content':
|
||||
'[Sprout event: stream message]\n'
|
||||
'[Buzz event: stream message]\n'
|
||||
'Content: @claude can you do that again?\n\n'
|
||||
'[Channel]\n'
|
||||
'#activity-test-channel',
|
||||
|
||||
@@ -5,18 +5,18 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel_detail_page.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel_management_provider.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel_messages_provider.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel_typing_provider.dart';
|
||||
import 'package:sprout_mobile/features/channels/channels_provider.dart';
|
||||
import 'package:sprout_mobile/features/channels/read_state/read_state_provider.dart';
|
||||
import 'package:sprout_mobile/features/profile/profile_provider.dart';
|
||||
import 'package:sprout_mobile/features/profile/user_cache_provider.dart';
|
||||
import 'package:sprout_mobile/features/profile/user_profile.dart';
|
||||
import 'package:sprout_mobile/shared/relay/relay.dart';
|
||||
import 'package:sprout_mobile/shared/theme/theme.dart';
|
||||
import 'package:buzz/features/channels/channel.dart';
|
||||
import 'package:buzz/features/channels/channel_detail_page.dart';
|
||||
import 'package:buzz/features/channels/channel_management_provider.dart';
|
||||
import 'package:buzz/features/channels/channel_messages_provider.dart';
|
||||
import 'package:buzz/features/channels/channel_typing_provider.dart';
|
||||
import 'package:buzz/features/channels/channels_provider.dart';
|
||||
import 'package:buzz/features/channels/read_state/read_state_provider.dart';
|
||||
import 'package:buzz/features/profile/profile_provider.dart';
|
||||
import 'package:buzz/features/profile/user_cache_provider.dart';
|
||||
import 'package:buzz/features/profile/user_profile.dart';
|
||||
import 'package:buzz/shared/relay/relay.dart';
|
||||
import 'package:buzz/shared/theme/theme.dart';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Test fixtures
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel_management_provider.dart';
|
||||
import 'package:sprout_mobile/shared/relay/relay.dart';
|
||||
import 'package:buzz/features/channels/channel_management_provider.dart';
|
||||
import 'package:buzz/shared/relay/relay.dart';
|
||||
|
||||
/// Tests for [channelDetailsFromEvent].
|
||||
///
|
||||
|
||||
@@ -2,8 +2,8 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel_messages_provider.dart';
|
||||
import 'package:sprout_mobile/shared/relay/relay.dart';
|
||||
import 'package:buzz/features/channels/channel_messages_provider.dart';
|
||||
import 'package:buzz/shared/relay/relay.dart';
|
||||
|
||||
void main() {
|
||||
test(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel_stars/channel_stars_storage.dart';
|
||||
import 'package:buzz/features/channels/channel_stars/channel_stars_storage.dart';
|
||||
|
||||
/// Tests for [ChannelStarStore] parsing and [mergeStores] last-writer-wins.
|
||||
void main() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel.dart';
|
||||
import 'package:buzz/features/channels/channel.dart';
|
||||
|
||||
void main() {
|
||||
group('Channel.fromJson', () {
|
||||
|
||||
@@ -2,13 +2,13 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:hooks_riverpod/misc.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel.dart';
|
||||
import 'package:sprout_mobile/features/channels/channels_page.dart';
|
||||
import 'package:sprout_mobile/features/channels/channels_provider.dart';
|
||||
import 'package:sprout_mobile/features/channels/read_state/read_state_provider.dart';
|
||||
import 'package:sprout_mobile/features/profile/profile_provider.dart';
|
||||
import 'package:sprout_mobile/features/profile/user_profile.dart';
|
||||
import 'package:sprout_mobile/shared/theme/theme.dart';
|
||||
import 'package:buzz/features/channels/channel.dart';
|
||||
import 'package:buzz/features/channels/channels_page.dart';
|
||||
import 'package:buzz/features/channels/channels_provider.dart';
|
||||
import 'package:buzz/features/channels/read_state/read_state_provider.dart';
|
||||
import 'package:buzz/features/profile/profile_provider.dart';
|
||||
import 'package:buzz/features/profile/user_profile.dart';
|
||||
import 'package:buzz/shared/theme/theme.dart';
|
||||
|
||||
void main() {
|
||||
Widget buildTestable({required List<Override> overrides}) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel_management_provider.dart';
|
||||
import 'package:sprout_mobile/features/channels/channels_provider.dart';
|
||||
import 'package:sprout_mobile/shared/relay/relay.dart';
|
||||
import 'package:buzz/features/channels/channel_management_provider.dart';
|
||||
import 'package:buzz/features/channels/channels_provider.dart';
|
||||
import 'package:buzz/shared/relay/relay.dart';
|
||||
|
||||
/// Tests for [ChannelsNotifier] in the pure-Nostr world.
|
||||
///
|
||||
|
||||
@@ -10,11 +10,11 @@ import 'package:http/testing.dart' as http_testing;
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:nostr/nostr.dart' as nostr;
|
||||
import 'package:sprout_mobile/features/channels/channel.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel_management_provider.dart';
|
||||
import 'package:sprout_mobile/features/channels/compose_bar.dart';
|
||||
import 'package:sprout_mobile/shared/relay/relay.dart';
|
||||
import 'package:sprout_mobile/shared/theme/theme.dart';
|
||||
import 'package:buzz/features/channels/channel.dart';
|
||||
import 'package:buzz/features/channels/channel_management_provider.dart';
|
||||
import 'package:buzz/features/channels/compose_bar.dart';
|
||||
import 'package:buzz/shared/relay/relay.dart';
|
||||
import 'package:buzz/shared/theme/theme.dart';
|
||||
|
||||
final _pngBytes = Uint8List.fromList([
|
||||
0x89,
|
||||
@@ -96,7 +96,7 @@ final _apngBytes = Uint8List.fromList([
|
||||
0x00,
|
||||
]);
|
||||
|
||||
const _mediaUploadPlatformChannel = MethodChannel('sprout/media_upload');
|
||||
const _mediaUploadPlatformChannel = MethodChannel('buzz/media_upload');
|
||||
|
||||
void _setMockMediaUploadPlatformHandler(
|
||||
Future<Object?> Function(MethodCall call)? handler,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/channels/date_formatters.dart';
|
||||
import 'package:buzz/features/channels/date_formatters.dart';
|
||||
|
||||
/// Helper: build a unix-second timestamp from a local DateTime.
|
||||
int _ts(DateTime local) => local.millisecondsSinceEpoch ~/ 1000;
|
||||
|
||||
@@ -3,9 +3,9 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:hooks_riverpod/misc.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:sprout_mobile/features/channels/message_content.dart';
|
||||
import 'package:sprout_mobile/features/channels/media_viewer_page.dart';
|
||||
import 'package:sprout_mobile/shared/theme/theme.dart';
|
||||
import 'package:buzz/features/channels/message_content.dart';
|
||||
import 'package:buzz/features/channels/media_viewer_page.dart';
|
||||
import 'package:buzz/shared/theme/theme.dart';
|
||||
|
||||
Widget _testable(Widget child, {List<Override> overrides = const []}) {
|
||||
return ProviderScope(
|
||||
@@ -245,16 +245,14 @@ void main() {
|
||||
testWidgets('renders markdown link', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
_testable(
|
||||
const MessageContent(
|
||||
content: 'Check [Sprout](https://example.com)',
|
||||
),
|
||||
const MessageContent(content: 'Check [Buzz](https://example.com)'),
|
||||
),
|
||||
);
|
||||
|
||||
final allText = _allRichText(tester);
|
||||
expect(allText, contains('Sprout'));
|
||||
expect(allText, contains('Buzz'));
|
||||
// Should not show raw markdown syntax.
|
||||
expect(allText, isNot(contains('[Sprout]')));
|
||||
expect(allText, isNot(contains('[Buzz]')));
|
||||
expect(allText, isNot(contains('(https://example.com)')));
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/channels/message_media.dart';
|
||||
import 'package:buzz/features/channels/message_media.dart';
|
||||
|
||||
void main() {
|
||||
group('classifyMediaUrl', () {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/channels/read_state/read_state_format.dart';
|
||||
import 'package:sprout_mobile/shared/relay/nostr_models.dart';
|
||||
import 'package:buzz/features/channels/read_state/read_state_format.dart';
|
||||
import 'package:buzz/shared/relay/nostr_models.dart';
|
||||
|
||||
void main() {
|
||||
group('read state event validation', () {
|
||||
|
||||
@@ -4,9 +4,9 @@ import 'dart:convert';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:nostr/nostr.dart' as nostr;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:sprout_mobile/features/channels/read_state/read_state_format.dart';
|
||||
import 'package:sprout_mobile/features/channels/read_state/read_state_manager.dart';
|
||||
import 'package:sprout_mobile/shared/relay/relay.dart';
|
||||
import 'package:buzz/features/channels/read_state/read_state_format.dart';
|
||||
import 'package:buzz/features/channels/read_state/read_state_manager.dart';
|
||||
import 'package:buzz/shared/relay/relay.dart';
|
||||
|
||||
void main() {
|
||||
test('dispose flushes a pending publish after marking disposed', () async {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/channels/read_state/read_state_time.dart';
|
||||
import 'package:buzz/features/channels/read_state/read_state_time.dart';
|
||||
|
||||
void main() {
|
||||
test('dateTimeToUnixSeconds converts DateTime values and nulls', () {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/channels/timeline_message.dart';
|
||||
import 'package:sprout_mobile/shared/relay/relay.dart';
|
||||
import 'package:buzz/features/channels/timeline_message.dart';
|
||||
import 'package:buzz/shared/relay/relay.dart';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
@@ -328,7 +328,7 @@ void main() {
|
||||
expect(result[0].content, 'keep');
|
||||
});
|
||||
|
||||
test('filters messages deleted via kind:9005 (Sprout-native)', () {
|
||||
test('filters messages deleted via kind:9005 (Buzz-native)', () {
|
||||
// Agents emit kind:9005 deletes via the CLI. Mobile must mirror desktop
|
||||
// and treat 9005 as a deletion marker, otherwise agent-deleted messages
|
||||
// stay rendered until manual refresh.
|
||||
|
||||
@@ -2,10 +2,10 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel.dart';
|
||||
import 'package:sprout_mobile/features/channels/channels_provider.dart';
|
||||
import 'package:sprout_mobile/features/channels/read_state/read_state_provider.dart';
|
||||
import 'package:sprout_mobile/features/channels/unread_badge/unread_badge_provider.dart';
|
||||
import 'package:buzz/features/channels/channel.dart';
|
||||
import 'package:buzz/features/channels/channels_provider.dart';
|
||||
import 'package:buzz/features/channels/read_state/read_state_provider.dart';
|
||||
import 'package:buzz/features/channels/unread_badge/unread_badge_provider.dart';
|
||||
|
||||
/// Unit tests for [unreadBadgeProvider].
|
||||
///
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/custom_emoji/custom_emoji.dart';
|
||||
import 'package:sprout_mobile/shared/relay/nostr_models.dart';
|
||||
import 'package:buzz/features/custom_emoji/custom_emoji.dart';
|
||||
import 'package:buzz/shared/relay/nostr_models.dart';
|
||||
|
||||
NostrEvent _event(String pubkey, List<List<String>> emojiTags) {
|
||||
return NostrEvent(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/features/forum/forum_models.dart';
|
||||
import 'package:buzz/features/forum/forum_models.dart';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:sprout_mobile/features/channels/channel.dart';
|
||||
import 'package:sprout_mobile/features/forum/forum_models.dart';
|
||||
import 'package:sprout_mobile/features/forum/forum_post_card.dart';
|
||||
import 'package:sprout_mobile/features/forum/forum_posts_view.dart';
|
||||
import 'package:sprout_mobile/features/forum/forum_provider.dart';
|
||||
import 'package:sprout_mobile/features/forum/forum_thread_page.dart';
|
||||
import 'package:sprout_mobile/features/profile/profile_provider.dart';
|
||||
import 'package:sprout_mobile/features/profile/user_cache_provider.dart';
|
||||
import 'package:sprout_mobile/features/profile/user_profile.dart';
|
||||
import 'package:sprout_mobile/shared/relay/relay.dart';
|
||||
import 'package:sprout_mobile/shared/theme/theme.dart';
|
||||
import 'package:buzz/features/channels/channel.dart';
|
||||
import 'package:buzz/features/forum/forum_models.dart';
|
||||
import 'package:buzz/features/forum/forum_post_card.dart';
|
||||
import 'package:buzz/features/forum/forum_posts_view.dart';
|
||||
import 'package:buzz/features/forum/forum_provider.dart';
|
||||
import 'package:buzz/features/forum/forum_thread_page.dart';
|
||||
import 'package:buzz/features/profile/profile_provider.dart';
|
||||
import 'package:buzz/features/profile/user_cache_provider.dart';
|
||||
import 'package:buzz/features/profile/user_profile.dart';
|
||||
import 'package:buzz/shared/relay/relay.dart';
|
||||
import 'package:buzz/shared/theme/theme.dart';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Test fixtures
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:sprout_mobile/features/pairing/pairing_page.dart';
|
||||
import 'package:sprout_mobile/features/pairing/pairing_provider.dart';
|
||||
import 'package:buzz/features/pairing/pairing_page.dart';
|
||||
import 'package:buzz/features/pairing/pairing_provider.dart';
|
||||
|
||||
import '../../helpers/widget_helpers.dart';
|
||||
|
||||
@@ -15,7 +15,7 @@ void main() {
|
||||
WidgetHelpers.testable(child: const PairingPage()),
|
||||
);
|
||||
|
||||
expect(find.text('Welcome to Sprout'), findsOneWidget);
|
||||
expect(find.text('Welcome to Buzz'), findsOneWidget);
|
||||
expect(find.text('Scan QR Code'), findsOneWidget);
|
||||
expect(find.text('or paste pairing code'), findsOneWidget);
|
||||
expect(find.text('Connect'), findsOneWidget);
|
||||
|
||||
@@ -2,10 +2,10 @@ import 'dart:convert';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:sprout_mobile/features/pairing/pairing_provider.dart';
|
||||
import 'package:sprout_mobile/shared/auth/auth.dart';
|
||||
import 'package:buzz/features/pairing/pairing_provider.dart';
|
||||
import 'package:buzz/shared/auth/auth.dart';
|
||||
|
||||
/// Tests for [PairingNotifier]'s legacy `sprout://` payload parsing and
|
||||
/// Tests for [PairingNotifier]'s legacy `buzz://` payload parsing and
|
||||
/// SSRF-prevention validation.
|
||||
///
|
||||
/// The pairing flow used to validate by calling `GET /api/users/me/profile`
|
||||
@@ -16,7 +16,7 @@ import 'package:sprout_mobile/shared/auth/auth.dart';
|
||||
///
|
||||
/// What we still cover here:
|
||||
/// - Initial state.
|
||||
/// - Parsing every documented payload format (raw base64, `sprout://`
|
||||
/// - Parsing every documented payload format (raw base64, `buzz://`
|
||||
/// prefix, whitespace).
|
||||
/// - Failure modes that return BEFORE any network call: invalid base64,
|
||||
/// wrong shape (non-object, missing fields, missing nsec), and SSRF
|
||||
@@ -57,6 +57,18 @@ void main() {
|
||||
expect(fakeAuth.lastWorkspace, isNull);
|
||||
});
|
||||
|
||||
test('accepts buzz scheme prefix', () async {
|
||||
container = createContainer();
|
||||
|
||||
final code = 'buzz://${_encodePairingCode()}';
|
||||
await container.read(pairingProvider.notifier).pair(code);
|
||||
|
||||
final state = container.read(pairingProvider);
|
||||
expect(state.status, PairingStatus.error);
|
||||
expect(state.errorMessage, contains('missing nsec'));
|
||||
expect(fakeAuth.lastWorkspace, isNull);
|
||||
});
|
||||
|
||||
test('invalid base64 sets format error', () async {
|
||||
container = createContainer();
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:sprout_mobile/features/profile/presence_cache_provider.dart';
|
||||
import 'package:sprout_mobile/shared/relay/relay.dart';
|
||||
import 'package:buzz/features/profile/presence_cache_provider.dart';
|
||||
import 'package:buzz/shared/relay/relay.dart';
|
||||
|
||||
/// Tests for [PresenceCacheNotifier] in the pure-Nostr world.
|
||||
///
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:sprout_mobile/features/profile/user_cache_provider.dart';
|
||||
import 'package:sprout_mobile/features/profile/user_profile.dart';
|
||||
import 'package:sprout_mobile/features/pulse/compose_note_page.dart';
|
||||
import 'package:sprout_mobile/features/pulse/pulse_models.dart';
|
||||
import 'package:sprout_mobile/shared/theme/theme.dart';
|
||||
import 'package:buzz/features/profile/user_cache_provider.dart';
|
||||
import 'package:buzz/features/profile/user_profile.dart';
|
||||
import 'package:buzz/features/pulse/compose_note_page.dart';
|
||||
import 'package:buzz/features/pulse/pulse_models.dart';
|
||||
import 'package:buzz/shared/theme/theme.dart';
|
||||
|
||||
class _FakeUserCacheNotifier extends UserCacheNotifier {
|
||||
final Map<String, UserProfile> _users;
|
||||
@@ -87,7 +87,7 @@ void main() {
|
||||
id: 'note2',
|
||||
pubkey: 'alice_pk',
|
||||
createdAt: DateTime.now().millisecondsSinceEpoch ~/ 1000 - 60,
|
||||
content: '#sprout\n',
|
||||
content: '#buzz\n',
|
||||
tags: const [
|
||||
[
|
||||
'imeta',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:hooks_riverpod/misc.dart';
|
||||
import 'package:sprout_mobile/shared/theme/theme.dart';
|
||||
import 'package:buzz/shared/theme/theme.dart';
|
||||
|
||||
class WidgetHelpers {
|
||||
static Widget testable({
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart' as http_testing;
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:nostr/nostr.dart' as nostr;
|
||||
import 'package:sprout_mobile/shared/relay/media_upload.dart';
|
||||
import 'package:buzz/shared/relay/media_upload.dart';
|
||||
|
||||
final _pngBytes = Uint8List.fromList([
|
||||
0x89,
|
||||
@@ -204,7 +204,7 @@ final _animatedWebpBytes = Uint8List.fromList([
|
||||
0x00,
|
||||
]);
|
||||
|
||||
const _mediaUploadPlatformChannel = MethodChannel('sprout/media_upload');
|
||||
const _mediaUploadPlatformChannel = MethodChannel('buzz/media_upload');
|
||||
|
||||
void _setMockMediaUploadPlatformHandler(
|
||||
Future<Object?> Function(MethodCall call)? handler,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:sprout_mobile/shared/relay/nostr_models.dart';
|
||||
import 'package:buzz/shared/relay/nostr_models.dart';
|
||||
|
||||
void main() {
|
||||
test('NostrFilter serializes and preserves authors', () {
|
||||
|
||||