diff --git a/lib/main.dart b/lib/main.dart index e8d2376..308a636 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,18 +5,18 @@ import 'theme/app_theme.dart'; import 'widgets/navigation/app_shell.dart'; void main() { - runApp(const ClaudeSessionViewerApp()); + runApp(const ClaudeSessionAnalysisApp()); } -class ClaudeSessionViewerApp extends StatelessWidget { - const ClaudeSessionViewerApp({super.key}); +class ClaudeSessionAnalysisApp extends StatelessWidget { + const ClaudeSessionAnalysisApp({super.key}); @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (_) => SessionProvider(), child: MaterialApp( - title: 'Claude Session Viewer', + title: 'Claude Session Analysis', debugShowCheckedModeBanner: false, theme: AppTheme.dark, home: const Scaffold( diff --git a/lib/screens/home/home_screen.dart b/lib/screens/home/home_screen.dart index 28cece3..8a7e59c 100644 --- a/lib/screens/home/home_screen.dart +++ b/lib/screens/home/home_screen.dart @@ -107,58 +107,58 @@ class _HomeScreenState extends State { _scanProjects(); } + /// Returns the real user home directory, even inside App Sandbox. + /// In sandbox, HOME points to ~/Library/Containers//Data. + String? _getRealHome() { + final home = Platform.environment['HOME']; + if (home == null) return null; + final match = RegExp(r'^(/Users/[^/]+)/Library/Containers/').firstMatch(home); + if (match != null) return match.group(1); + return home; + } + /// Converts the encoded dir name to a human-readable project name. /// "-Users-mathias-Documents-workspaces-svrnty-talos-rpi5" → "svrnty / talos-rpi5" /// "-Users-mathias" → "~ (home)" - /// "-Applications-Auto-Claude-app-Contents-Resources-backend" → "Auto-Claude / backend" String _parsePrettyName(String dirName) { - // Reconstruct the original path: leading - is /, inner - are / - // But careful: "a-gent-maf-debug" is a single folder name with dashes. - // The trick: the encoded path uses - as separator for EVERY path component. - // We know the common prefixes so we can strip them. - String path = dirName; + final home = _getRealHome() ?? ''; + final username = home.split('/').last; - // Strip known prefixes to get to the interesting part + // Try to reconstruct the actual filesystem path + final reconstructed = _reconstructPath(dirName, home); + if (reconstructed != null) { + final segs = reconstructed.split('/').where((s) => s.isNotEmpty).toList(); + // Remove common uninteresting segments + final skip = {'Users', username, 'Documents', 'workspaces', 'Workspaces', + 'Applications', 'Contents', 'Resources', 'Volumes'}; + final meaningful = segs.where((s) => !skip.contains(s)).toList(); + if (meaningful.isEmpty) return '~ (home)'; + if (meaningful.length >= 2) { + return '${meaningful[meaningful.length - 2]} / ${meaningful.last}'; + } + return meaningful.last; + } + + // Fallback: build dynamic prefixes from the detected username final prefixes = [ - '-Users-mathias-Documents-workspaces-', - '-Users-mathias-Documents-', - '-Users-mathias-', + '-Users-$username-Documents-workspaces-', + '-Users-$username-Documents-', + '-Users-$username-Workspaces-', + '-Users-$username-', + '-Volumes-Workspaces-', + '-Volumes-', '-Applications-', ]; - String prefix = ''; + String path = dirName; for (final p in prefixes) { if (path.startsWith(p)) { - prefix = p; path = path.substring(p.length); break; } } - if (path.isEmpty) { - if (dirName == '-Users-mathias') return '~ (home)'; - return dirName; - } - - // Now `path` is something like "svrnty-talos-rpi5--out-fondation" - // Double dashes (--) were actual dashes in folder names? No — they represent - // a subfolder that itself has a dash. We need to figure out the actual - // filesystem path. Let's just check if the reconstructed path exists. - final home = Platform.environment['HOME'] ?? ''; - final reconstructed = _reconstructPath(dirName, home); - if (reconstructed != null) { - // Get last 2 meaningful segments - final segs = reconstructed.split('/').where((s) => s.isNotEmpty).toList(); - // Remove common uninteresting segments - final skip = {'Users', 'mathias', 'Documents', 'workspaces', 'Applications', 'Contents', 'Resources'}; - final meaningful = segs.where((s) => !skip.contains(s)).toList(); - if (meaningful.length >= 2) { - return '${meaningful[meaningful.length - 2]} / ${meaningful.last}'; - } - if (meaningful.isNotEmpty) return meaningful.last; - } - - // Fallback: just clean up the raw name + if (path.isEmpty) return '~ (home)'; return path.replaceAll('--', ' / ').replaceAll('-', ' '); } @@ -200,18 +200,48 @@ class _HomeScreenState extends State { return result; // return anyway as best guess } + /// Locates the Claude Code data directory. + /// Claude Code always stores data at ~/.claude/ regardless of where + /// the binary is installed (npm global, homebrew, etc). + Future _findClaudeDataDir() async { + final home = _getRealHome(); + debugPrint('[Claude] HOME env: ${Platform.environment['HOME']}'); + debugPrint('[Claude] Real home resolved to: $home'); + + if (home == null) { + debugPrint('[Claude] ERROR: Could not determine home directory'); + return null; + } + + final claudeDir = Directory('$home/.claude'); + final exists = await claudeDir.exists(); + debugPrint('[Claude] Checking ${claudeDir.path} -> exists: $exists'); + + if (exists) return claudeDir; + + return null; + } + Future _scanProjects() async { - final home = Platform.environment['HOME']; - if (home == null) return; - final claudeDir = Directory('$home/.claude/projects'); - if (!await claudeDir.exists()) { + final claudeData = await _findClaudeDataDir(); + if (claudeData == null) { + debugPrint('[Claude] No Claude Code data directory found'); setState(() => _scanning = false); return; } + final projectsDir = Directory('${claudeData.path}/projects'); + final projExists = await projectsDir.exists(); + debugPrint('[Claude] Projects dir: ${projectsDir.path} -> exists: $projExists'); + if (!projExists) { + setState(() => _scanning = false); + return; + } + + final home = _getRealHome() ?? ''; final projects = <_Project>[]; - await for (final projectDir in claudeDir.list()) { + await for (final projectDir in projectsDir.list()) { if (projectDir is! Directory) continue; final dirName = projectDir.path.split('/').last; @@ -220,9 +250,7 @@ class _HomeScreenState extends State { // Scan .jsonl files in the project dir try { await for (final entity in projectDir.list()) { - if (entity is File && - entity.path.endsWith('.jsonl') && - !entity.path.endsWith('sessions-index.json')) { + if (entity is File && entity.path.endsWith('.jsonl')) { try { final stat = entity.statSync(); final fileName = entity.path.split('/').last; @@ -236,26 +264,6 @@ class _HomeScreenState extends State { } } catch (_) {} - // Also scan sessions/ subdirectory - final sessionsDir = Directory('${projectDir.path}/sessions'); - if (await sessionsDir.exists()) { - try { - await for (final entity in sessionsDir.list()) { - if (entity is File && entity.path.endsWith('.jsonl')) { - try { - final stat = entity.statSync(); - final fileName = entity.path.split('/').last; - sessions.add(_SessionFile( - file: entity, - stat: stat, - sessionId: fileName.replaceAll('.jsonl', ''), - )); - } catch (_) {} - } - } - } catch (_) {} - } - if (sessions.isEmpty) continue; sessions.sort((a, b) => b.stat.modified.compareTo(a.stat.modified)); @@ -283,7 +291,7 @@ class _HomeScreenState extends State { } Future _pickFile() async { - final home = Platform.environment['HOME'] ?? ''; + final home = _getRealHome() ?? ''; final result = await FilePicker.platform.pickFiles( type: FileType.custom, allowedExtensions: ['jsonl'], diff --git a/lib/widgets/navigation/sidebar.dart b/lib/widgets/navigation/sidebar.dart index d346f1e..17edf18 100644 --- a/lib/widgets/navigation/sidebar.dart +++ b/lib/widgets/navigation/sidebar.dart @@ -48,7 +48,7 @@ class Sidebar extends StatelessWidget { ), const SizedBox(width: 10), const Text( - 'Session Viewer', + 'Session Analysis', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -107,7 +107,7 @@ class Sidebar extends StatelessWidget { Padding( padding: const EdgeInsets.all(16), child: Text( - 'Claude Session Viewer v0.1', + 'Claude Session Analysis v1.0', style: TextStyle( fontSize: 10, color: AppColors.textMuted.withAlpha(128), diff --git a/macos/Podfile b/macos/Podfile index ff5ddb3..65543e2 100644 --- a/macos/Podfile +++ b/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.15' +platform :osx, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 6ebac85..2f9466e 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,29 +1,16 @@ PODS: - - file_picker (0.0.1): - - FlutterMacOS - FlutterMacOS (1.0.0) - - shared_preferences_foundation (0.0.1): - - Flutter - - FlutterMacOS DEPENDENCIES: - - file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) EXTERNAL SOURCES: - file_picker: - :path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos FlutterMacOS: :path: Flutter/ephemeral - shared_preferences_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin SPEC CHECKSUMS: - file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 - shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb -PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009 +PODFILE CHECKSUM: 89c84cf5c2351c1e554c6dea18d31a879fc3a19e COCOAPODS: 1.16.2 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index c7878b9..4d70757 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC10FF2044A3C60003C045 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10FE2044A3C60003C045 /* PrivacyInfo.xcprivacy */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 79F3DEC2140214566E19F388 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CB8C54BF040E1E6BF05BCBD /* Pods_RunnerTests.framework */; }; @@ -68,7 +69,7 @@ 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* claude_session_viewer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = claude_session_viewer.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* Claude Session Analysis.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Claude Session Analysis.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -77,6 +78,7 @@ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33CC10FE2044A3C60003C045 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; @@ -147,7 +149,7 @@ 33CC10EE2044A3C60003C045 /* Products */ = { isa = PBXGroup; children = ( - 33CC10ED2044A3C60003C045 /* claude_session_viewer.app */, + 33CC10ED2044A3C60003C045 /* Claude Session Analysis.app */, 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, ); name = Products; @@ -181,6 +183,7 @@ children = ( 33CC10F02044A3C60003C045 /* AppDelegate.swift */, 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33CC10FE2044A3C60003C045 /* PrivacyInfo.xcprivacy */, 33E51913231747F40026EE4D /* DebugProfile.entitlements */, 33E51914231749380026EE4D /* Release.entitlements */, 33CC11242044D66E0003C045 /* Resources */, @@ -244,7 +247,6 @@ 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, - 2C302F33045D329C15CB5562 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -256,7 +258,7 @@ 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, ); productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* claude_session_viewer.app */; + productReference = 33CC10ED2044A3C60003C045 /* Claude Session Analysis.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -327,29 +329,13 @@ files = ( 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + 33CC10FF2044A3C60003C045 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 2C302F33045D329C15CB5562 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 2D5E86AC9DD4210FFD8C9DE8 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -489,10 +475,10 @@ CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.svrnty.claudeSessionViewer.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = com.svrnty.claudeSessionAnalysis.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/claude_session_viewer.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/claude_session_viewer"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Claude Session Analysis.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Claude Session Analysis"; }; name = Debug; }; @@ -504,10 +490,10 @@ CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.svrnty.claudeSessionViewer.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = com.svrnty.claudeSessionAnalysis.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/claude_session_viewer.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/claude_session_viewer"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Claude Session Analysis.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Claude Session Analysis"; }; name = Release; }; @@ -519,10 +505,10 @@ CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.svrnty.claudeSessionViewer.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = com.svrnty.claudeSessionAnalysis.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/claude_session_viewer.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/claude_session_viewer"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Claude Session Analysis.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Claude Session Analysis"; }; name = Profile; }; @@ -567,7 +553,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -649,7 +635,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -699,7 +685,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig index 4dfff64..619cea5 100644 --- a/macos/Runner/Configs/AppInfo.xcconfig +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -5,10 +5,10 @@ // 'flutter create' template. // The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = claude_session_viewer +PRODUCT_NAME = Claude Session Analysis // The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.svrnty.claudeSessionViewer +PRODUCT_BUNDLE_IDENTIFIER = com.svrnty.claudeSessionAnalysis // The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2026 com.svrnty. All rights reserved. +PRODUCT_COPYRIGHT = Copyright © 2026 Svrnty. All rights reserved. diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist index 4789daa..ad3abd1 100644 --- a/macos/Runner/Info.plist +++ b/macos/Runner/Info.plist @@ -22,6 +22,8 @@ $(FLUTTER_BUILD_NUMBER) LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) + LSApplicationCategoryType + public.app-category.developer-tools NSHumanReadableCopyright $(PRODUCT_COPYRIGHT) NSMainNibFile diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift index 79904a8..e32fed7 100644 --- a/macos/Runner/MainFlutterWindow.swift +++ b/macos/Runner/MainFlutterWindow.swift @@ -8,7 +8,7 @@ class MainFlutterWindow: NSWindow { self.contentViewController = flutterViewController self.setFrame(windowFrame, display: true) self.minSize = NSSize(width: 1200, height: 700) - self.title = "Claude Session Viewer" + self.title = "Claude Session Analysis" RegisterGeneratedPlugins(registry: flutterViewController) diff --git a/macos/Runner/PrivacyInfo.xcprivacy b/macos/Runner/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..dba570d --- /dev/null +++ b/macos/Runner/PrivacyInfo.xcprivacy @@ -0,0 +1,31 @@ + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + + diff --git a/pubspec.lock b/pubspec.lock index 731eeb0..4ad86e5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -29,10 +29,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" clock: dependency: transitive description: @@ -276,18 +276,18 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.19" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: @@ -521,10 +521,10 @@ packages: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "0.7.10" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 0a1d4a2..890fad2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ -name: claude_session_viewer -description: "A new Flutter project." +name: claude_session_analysis +description: "Analyze and explore Claude Code session transcripts with rich visualizations, token usage tracking, and agent timeline views." # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/test/widget_test.dart b/test/widget_test.dart index f575efa..c10da65 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1,9 +1,9 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:claude_session_viewer/main.dart'; +import 'package:claude_session_analysis/main.dart'; void main() { testWidgets('App launches', (WidgetTester tester) async { - await tester.pumpWidget(const ClaudeSessionViewerApp()); - expect(find.text('Claude Session Viewer'), findsOneWidget); + await tester.pumpWidget(const ClaudeSessionAnalysisApp()); + expect(find.text('Claude Session Analysis'), findsOneWidget); }); }