Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
780ef9378f | ||
|
|
0b72c679bc | ||
|
|
df23483278 | ||
|
|
e658c6c9cf | ||
|
|
ee06c97c06 | ||
|
|
f6b496dad7 | ||
|
|
53ed5a6cd1 | ||
|
|
5c693bf3d8 |
@ -22,8 +22,8 @@ class ContentBlock {
|
|||||||
class TextBlock extends ContentBlock {
|
class TextBlock extends ContentBlock {
|
||||||
final String text;
|
final String text;
|
||||||
|
|
||||||
TextBlock({required this.text, required Map<String, dynamic> raw})
|
TextBlock({required this.text, required super.raw})
|
||||||
: super(type: 'text', raw: raw);
|
: super(type: 'text');
|
||||||
|
|
||||||
factory TextBlock.fromJson(Map<String, dynamic> json) {
|
factory TextBlock.fromJson(Map<String, dynamic> json) {
|
||||||
return TextBlock(
|
return TextBlock(
|
||||||
@ -40,8 +40,8 @@ class ThinkingBlock extends ContentBlock {
|
|||||||
ThinkingBlock({
|
ThinkingBlock({
|
||||||
required this.thinking,
|
required this.thinking,
|
||||||
this.signature,
|
this.signature,
|
||||||
required Map<String, dynamic> raw,
|
required super.raw,
|
||||||
}) : super(type: 'thinking', raw: raw);
|
}) : super(type: 'thinking');
|
||||||
|
|
||||||
factory ThinkingBlock.fromJson(Map<String, dynamic> json) {
|
factory ThinkingBlock.fromJson(Map<String, dynamic> json) {
|
||||||
return ThinkingBlock(
|
return ThinkingBlock(
|
||||||
@ -63,8 +63,8 @@ class ToolUseBlock extends ContentBlock {
|
|||||||
required this.name,
|
required this.name,
|
||||||
required this.input,
|
required this.input,
|
||||||
this.linkedResult,
|
this.linkedResult,
|
||||||
required Map<String, dynamic> raw,
|
required super.raw,
|
||||||
}) : super(type: 'tool_use', raw: raw);
|
}) : super(type: 'tool_use');
|
||||||
|
|
||||||
factory ToolUseBlock.fromJson(Map<String, dynamic> json) {
|
factory ToolUseBlock.fromJson(Map<String, dynamic> json) {
|
||||||
return ToolUseBlock(
|
return ToolUseBlock(
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:file_picker/file_picker.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import '../../providers/session_provider.dart';
|
import '../../providers/session_provider.dart';
|
||||||
|
import '../../services/native_picker.dart';
|
||||||
import '../../theme/app_theme.dart';
|
import '../../theme/app_theme.dart';
|
||||||
|
|
||||||
// ─── Data models ─────────────────────────────────────────────
|
// ─── Data models ─────────────────────────────────────────────
|
||||||
@ -100,15 +100,27 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
bool _scanning = true;
|
bool _scanning = true;
|
||||||
String _searchQuery = '';
|
String _searchQuery = '';
|
||||||
_Project? _selectedProject;
|
_Project? _selectedProject;
|
||||||
|
_Project? _customFolderProject;
|
||||||
|
final _pathController = TextEditingController();
|
||||||
|
final _pathFocusNode = FocusNode();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
final home = _getRealHome() ?? '';
|
||||||
|
_pathController.text = '$home/.claude/projects';
|
||||||
_scanProjects();
|
_scanProjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_pathController.dispose();
|
||||||
|
_pathFocusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the real user home directory, even inside App Sandbox.
|
/// Returns the real user home directory, even inside App Sandbox.
|
||||||
/// In sandbox, HOME points to ~/Library/Containers/<bundleid>/Data.
|
/// In sandbox, HOME points to `~/Library/Containers/bundleid/Data`.
|
||||||
String? _getRealHome() {
|
String? _getRealHome() {
|
||||||
final home = Platform.environment['HOME'];
|
final home = Platform.environment['HOME'];
|
||||||
if (home == null) return null;
|
if (home == null) return null;
|
||||||
@ -290,15 +302,130 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _pickFile() async {
|
/// Resolve a path string, expanding ~ to the home directory.
|
||||||
final home = _getRealHome() ?? '';
|
String _resolvePath(String input) {
|
||||||
final result = await FilePicker.platform.pickFiles(
|
final home = _getRealHome() ?? Platform.environment['HOME'] ?? '';
|
||||||
type: FileType.custom,
|
var path = input.trim();
|
||||||
allowedExtensions: ['jsonl'],
|
if (path.startsWith('~/')) {
|
||||||
initialDirectory: '$home/.claude/projects',
|
path = '$home${path.substring(1)}';
|
||||||
);
|
} else if (path == '~') {
|
||||||
if (result != null && result.files.single.path != null) {
|
path = home;
|
||||||
await _loadFile(result.files.single.path!);
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _scanFromPathInput() async {
|
||||||
|
final resolved = _resolvePath(_pathController.text);
|
||||||
|
final dir = Directory(resolved);
|
||||||
|
if (await dir.exists()) {
|
||||||
|
await _scanFolder(resolved);
|
||||||
|
} else {
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('Folder not found: $resolved'),
|
||||||
|
backgroundColor: AppColors.error,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _pickFolder() async {
|
||||||
|
try {
|
||||||
|
final home = _getRealHome() ?? '';
|
||||||
|
final result = await NativePicker.getDirectoryPath(
|
||||||
|
initialDirectory: '$home/.claude/projects',
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
_pathController.text = result;
|
||||||
|
await _scanFolder(result);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('[Browse] Error: $e');
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('Could not open folder picker: $e'),
|
||||||
|
backgroundColor: AppColors.error,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _scanFolder(String folderPath) async {
|
||||||
|
setState(() {
|
||||||
|
_scanning = true;
|
||||||
|
_selectedProject = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
final sessions = <_SessionFile>[];
|
||||||
|
|
||||||
|
// Recursively scan for .jsonl files
|
||||||
|
final dir = Directory(folderPath);
|
||||||
|
if (await dir.exists()) {
|
||||||
|
await _scanFolderRecursive(dir, sessions);
|
||||||
|
}
|
||||||
|
|
||||||
|
sessions.sort((a, b) => b.stat.modified.compareTo(a.stat.modified));
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_customFolderProject = _Project(
|
||||||
|
dirPath: folderPath,
|
||||||
|
rawDirName: folderPath.split('/').last,
|
||||||
|
displayName: folderPath.split('/').last,
|
||||||
|
fullPath: folderPath,
|
||||||
|
sessions: sessions,
|
||||||
|
lastModified: sessions.isNotEmpty ? sessions.first.stat.modified : DateTime.now(),
|
||||||
|
);
|
||||||
|
_selectedProject = _customFolderProject;
|
||||||
|
_scanning = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _scanFolderRecursive(Directory dir, List<_SessionFile> sessions) async {
|
||||||
|
try {
|
||||||
|
await for (final entity in dir.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 (_) {}
|
||||||
|
} else if (entity is Directory) {
|
||||||
|
await _scanFolderRecursive(entity, sessions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadSingleFile() async {
|
||||||
|
try {
|
||||||
|
final home = _getRealHome() ?? '';
|
||||||
|
final result = await NativePicker.pickFile(
|
||||||
|
allowedExtensions: ['jsonl'],
|
||||||
|
initialDirectory: '$home/.claude/projects',
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
await _loadFile(result);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('[Load] Error: $e');
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('Could not open file picker: $e'),
|
||||||
|
backgroundColor: AppColors.error,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,68 +516,161 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
// ─── Header with breadcrumb ──────────────────────────────
|
// ─── Header with breadcrumb ──────────────────────────────
|
||||||
|
|
||||||
Widget _buildHeader(SessionProvider provider) {
|
Widget _buildHeader(SessionProvider provider) {
|
||||||
return Row(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.terminal, size: 24, color: AppColors.assistant),
|
// Row 1: breadcrumb + count
|
||||||
const SizedBox(width: 10),
|
Row(
|
||||||
// Breadcrumb
|
children: [
|
||||||
InkWell(
|
const Icon(Icons.terminal, size: 24, color: AppColors.assistant),
|
||||||
onTap: () => setState(() => _selectedProject = null),
|
const SizedBox(width: 10),
|
||||||
borderRadius: BorderRadius.circular(4),
|
InkWell(
|
||||||
child: Text(
|
onTap: () => setState(() => _selectedProject = null),
|
||||||
'Projects',
|
borderRadius: BorderRadius.circular(4),
|
||||||
style: TextStyle(
|
child: Text(
|
||||||
fontSize: 18,
|
'Projects',
|
||||||
fontWeight: FontWeight.bold,
|
style: TextStyle(
|
||||||
color: _selectedProject != null
|
fontSize: 18,
|
||||||
? AppColors.assistant
|
fontWeight: FontWeight.bold,
|
||||||
: AppColors.textPrimary,
|
color: _selectedProject != null
|
||||||
decoration: _selectedProject != null
|
? AppColors.assistant
|
||||||
? TextDecoration.underline
|
: AppColors.textPrimary,
|
||||||
: TextDecoration.none,
|
decoration: _selectedProject != null
|
||||||
decorationColor: AppColors.assistant,
|
? TextDecoration.underline
|
||||||
),
|
: TextDecoration.none,
|
||||||
),
|
decorationColor: AppColors.assistant,
|
||||||
),
|
),
|
||||||
if (_selectedProject != null) ...[
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
|
||||||
child: Icon(Icons.chevron_right, size: 18, color: AppColors.textMuted),
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
_selectedProject!.displayName,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: AppColors.textPrimary,
|
|
||||||
),
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
),
|
||||||
),
|
if (_selectedProject != null) ...[
|
||||||
],
|
const Padding(
|
||||||
const Spacer(),
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
Text(
|
child: Icon(Icons.chevron_right, size: 18, color: AppColors.textMuted),
|
||||||
_selectedProject != null
|
),
|
||||||
? '${_selectedProject!.sessionCount} session${_selectedProject!.sessionCount == 1 ? '' : 's'}'
|
Flexible(
|
||||||
: '${_projects.length} projects',
|
child: Text(
|
||||||
style: const TextStyle(fontSize: 12, color: AppColors.textMuted),
|
_selectedProject!.displayName,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
const Spacer(),
|
||||||
|
Text(
|
||||||
|
_selectedProject != null
|
||||||
|
? '${_selectedProject!.sessionCount} session${_selectedProject!.sessionCount == 1 ? '' : 's'}'
|
||||||
|
: '${_projects.length} projects',
|
||||||
|
style: const TextStyle(fontSize: 12, color: AppColors.textMuted),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(height: 12),
|
||||||
ElevatedButton.icon(
|
// Row 2: path input + Load + Browse
|
||||||
onPressed: _pickFile,
|
Row(
|
||||||
icon: const Icon(Icons.folder_open, size: 14),
|
children: [
|
||||||
label: const Text('Browse'),
|
// Path input field — flexible to fill available space
|
||||||
style: ElevatedButton.styleFrom(
|
Expanded(
|
||||||
backgroundColor: AppColors.surfaceLight,
|
child: SizedBox(
|
||||||
foregroundColor: AppColors.textPrimary,
|
height: 36,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
|
child: TextField(
|
||||||
shape: RoundedRectangleBorder(
|
controller: _pathController,
|
||||||
borderRadius: BorderRadius.circular(6),
|
focusNode: _pathFocusNode,
|
||||||
side: const BorderSide(color: AppColors.surfaceBorder),
|
style: const TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: AppColors.textPrimary,
|
||||||
|
fontFamily: 'JetBrains Mono',
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Path to scan (e.g. ~/.claude/projects)',
|
||||||
|
hintStyle: const TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: AppColors.textMuted,
|
||||||
|
fontFamily: 'JetBrains Mono',
|
||||||
|
),
|
||||||
|
isDense: true,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor: AppColors.surface,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
borderSide: const BorderSide(color: AppColors.surfaceBorder),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
borderSide: const BorderSide(color: AppColors.surfaceBorder),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
borderSide: const BorderSide(color: AppColors.assistant),
|
||||||
|
),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_forward, size: 14,
|
||||||
|
color: AppColors.textMuted),
|
||||||
|
tooltip: 'Scan this folder',
|
||||||
|
onPressed: _scanFromPathInput,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onSubmitted: (_) => _scanFromPathInput(),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
textStyle: const TextStyle(fontSize: 12),
|
const SizedBox(width: 8),
|
||||||
),
|
SizedBox(
|
||||||
|
height: 36,
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
onPressed: _loadSingleFile,
|
||||||
|
icon: const Icon(Icons.insert_drive_file_outlined, size: 14),
|
||||||
|
label: const Text('Load'),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: AppColors.surfaceLight,
|
||||||
|
foregroundColor: AppColors.textPrimary,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 0),
|
||||||
|
minimumSize: Size.zero,
|
||||||
|
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
side: const BorderSide(color: AppColors.surfaceBorder),
|
||||||
|
),
|
||||||
|
textStyle: const TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
SizedBox(
|
||||||
|
height: 36,
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
onPressed: _pickFolder,
|
||||||
|
icon: const Icon(Icons.folder_open, size: 14),
|
||||||
|
label: const Text('Browse'),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: AppColors.surfaceLight,
|
||||||
|
foregroundColor: AppColors.textPrimary,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 0),
|
||||||
|
minimumSize: Size.zero,
|
||||||
|
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
side: const BorderSide(color: AppColors.surfaceBorder),
|
||||||
|
),
|
||||||
|
textStyle: const TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Tooltip(
|
||||||
|
message: 'Type a path with hidden folders directly in the input field',
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 4),
|
||||||
|
child: Icon(Icons.info_outline, size: 14, color: AppColors.textMuted),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
41
lib/services/native_picker.dart
Normal file
41
lib/services/native_picker.dart
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
/// Native file picker that shows hidden files/folders on macOS.
|
||||||
|
/// Uses a custom method channel to NSOpenPanel with showsHiddenFiles = true,
|
||||||
|
/// which the file_picker package hardcodes to false.
|
||||||
|
class NativePicker {
|
||||||
|
static const _channel = MethodChannel('com.svrnty.native_picker');
|
||||||
|
|
||||||
|
/// Opens a folder picker that shows hidden directories.
|
||||||
|
/// Returns the selected folder path, or null if cancelled.
|
||||||
|
static Future<String?> getDirectoryPath({String? initialDirectory}) async {
|
||||||
|
try {
|
||||||
|
return _channel.invokeMethod<String?>('getDirectoryPath', {
|
||||||
|
'initialDirectory': initialDirectory,
|
||||||
|
});
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
throw Exception('Native picker error: ${e.message}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Opens a file picker that shows hidden files, filtered to specific extensions.
|
||||||
|
/// Returns the selected file path, or null if cancelled.
|
||||||
|
static Future<String?> pickFile({
|
||||||
|
List<String> allowedExtensions = const [],
|
||||||
|
String? initialDirectory,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final result = await _channel.invokeMethod<List?>('pickFiles', {
|
||||||
|
'allowMultiple': false,
|
||||||
|
'allowedExtensions': allowedExtensions,
|
||||||
|
'initialDirectory': initialDirectory,
|
||||||
|
});
|
||||||
|
if (result != null && result.isNotEmpty) {
|
||||||
|
return result.first as String;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
throw Exception('Native picker error: ${e.message}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,2 +1 @@
|
|||||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
|
||||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||||
|
|||||||
@ -1,2 +1 @@
|
|||||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
|
||||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||||
|
|||||||
@ -1,42 +0,0 @@
|
|||||||
platform :osx, '13.0'
|
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
|
||||||
|
|
||||||
project 'Runner', {
|
|
||||||
'Debug' => :debug,
|
|
||||||
'Profile' => :release,
|
|
||||||
'Release' => :release,
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutter_root
|
|
||||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
|
|
||||||
unless File.exist?(generated_xcode_build_settings_path)
|
|
||||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
|
|
||||||
end
|
|
||||||
|
|
||||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
|
||||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
|
||||||
return matches[1].strip if matches
|
|
||||||
end
|
|
||||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
|
|
||||||
end
|
|
||||||
|
|
||||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
|
||||||
|
|
||||||
flutter_macos_podfile_setup
|
|
||||||
|
|
||||||
target 'Runner' do
|
|
||||||
use_frameworks!
|
|
||||||
|
|
||||||
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
|
|
||||||
target 'RunnerTests' do
|
|
||||||
inherit! :search_paths
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
post_install do |installer|
|
|
||||||
installer.pods_project.targets.each do |target|
|
|
||||||
flutter_additional_macos_build_settings(target)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
PODS:
|
|
||||||
- FlutterMacOS (1.0.0)
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
|
||||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
|
||||||
FlutterMacOS:
|
|
||||||
:path: Flutter/ephemeral
|
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
|
||||||
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: 89c84cf5c2351c1e554c6dea18d31a879fc3a19e
|
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
|
||||||
@ -21,16 +21,15 @@
|
|||||||
/* End PBXAggregateTarget section */
|
/* End PBXAggregateTarget section */
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
130C39CAC9CC7AA143C489DF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8D4F4D6A14DBC06CABB730 /* Pods_Runner.framework */; };
|
|
||||||
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
|
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
|
||||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
|
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
|
||||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
|
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
|
||||||
|
AABB001B1B1B1B1B1B1B /* NativePickerRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = AABB001A1A1A1A1A1A1A /* NativePickerRegistrar.swift */; };
|
||||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
||||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
||||||
33CC10FF2044A3C60003C045 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10FE2044A3C60003C045 /* PrivacyInfo.xcprivacy */; };
|
33CC10FF2044A3C60003C045 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10FE2044A3C60003C045 /* PrivacyInfo.xcprivacy */; };
|
||||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
||||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
|
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
|
||||||
79F3DEC2140214566E19F388 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CB8C54BF040E1E6BF05BCBD /* Pods_RunnerTests.framework */; };
|
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -64,34 +63,27 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
153C2DDE069AD579210ED2C4 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
||||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
||||||
33CC10ED2044A3C60003C045 /* Claude Session Analysis.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Claude Session Analysis.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 = "<group>"; };
|
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
AABB001A1A1A1A1A1A1A /* NativePickerRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativePickerRegistrar.swift; sourceTree = "<group>"; };
|
||||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||||
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
|
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
|
||||||
|
33CC10FE2044A3C60003C045 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
|
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
|
||||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
|
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
|
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
|
||||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
|
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
|
||||||
33CC10FE2044A3C60003C045 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
|
||||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
|
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
|
||||||
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
||||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
||||||
4BD835AFFC7FFFD2AC416CAE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
4C8D4F4D6A14DBC06CABB730 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
4EB19377A730AE2C095D7A54 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
6CB8C54BF040E1E6BF05BCBD /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
|
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||||
881127F55C6D6CFE2534841B /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
A5398467BE6DA3EC050E790F /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
C0A0ADC8E8ED2668AF72715E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -99,7 +91,6 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
79F3DEC2140214566E19F388 /* Pods_RunnerTests.framework in Frameworks */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -108,7 +99,6 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
|
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
|
||||||
130C39CAC9CC7AA143C489DF /* Pods_Runner.framework in Frameworks */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -141,8 +131,6 @@
|
|||||||
33CEB47122A05771004F2AC0 /* Flutter */,
|
33CEB47122A05771004F2AC0 /* Flutter */,
|
||||||
331C80D6294CF71000263BE5 /* RunnerTests */,
|
331C80D6294CF71000263BE5 /* RunnerTests */,
|
||||||
33CC10EE2044A3C60003C045 /* Products */,
|
33CC10EE2044A3C60003C045 /* Products */,
|
||||||
D73912EC22F37F3D000D13A0 /* Frameworks */,
|
|
||||||
8208943E7AB9C5C3402F88ED /* Pods */,
|
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@ -182,6 +170,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
|
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
|
||||||
|
AABB001A1A1A1A1A1A1A /* NativePickerRegistrar.swift */,
|
||||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
|
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
|
||||||
33CC10FE2044A3C60003C045 /* PrivacyInfo.xcprivacy */,
|
33CC10FE2044A3C60003C045 /* PrivacyInfo.xcprivacy */,
|
||||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
|
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
|
||||||
@ -192,29 +181,6 @@
|
|||||||
path = Runner;
|
path = Runner;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
8208943E7AB9C5C3402F88ED /* Pods */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
153C2DDE069AD579210ED2C4 /* Pods-Runner.debug.xcconfig */,
|
|
||||||
C0A0ADC8E8ED2668AF72715E /* Pods-Runner.release.xcconfig */,
|
|
||||||
4BD835AFFC7FFFD2AC416CAE /* Pods-Runner.profile.xcconfig */,
|
|
||||||
881127F55C6D6CFE2534841B /* Pods-RunnerTests.debug.xcconfig */,
|
|
||||||
4EB19377A730AE2C095D7A54 /* Pods-RunnerTests.release.xcconfig */,
|
|
||||||
A5398467BE6DA3EC050E790F /* Pods-RunnerTests.profile.xcconfig */,
|
|
||||||
);
|
|
||||||
name = Pods;
|
|
||||||
path = Pods;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
4C8D4F4D6A14DBC06CABB730 /* Pods_Runner.framework */,
|
|
||||||
6CB8C54BF040E1E6BF05BCBD /* Pods_RunnerTests.framework */,
|
|
||||||
);
|
|
||||||
name = Frameworks;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@ -222,7 +188,6 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
2D5E86AC9DD4210FFD8C9DE8 /* [CP] Check Pods Manifest.lock */,
|
|
||||||
331C80D1294CF70F00263BE5 /* Sources */,
|
331C80D1294CF70F00263BE5 /* Sources */,
|
||||||
331C80D2294CF70F00263BE5 /* Frameworks */,
|
331C80D2294CF70F00263BE5 /* Frameworks */,
|
||||||
331C80D3294CF70F00263BE5 /* Resources */,
|
331C80D3294CF70F00263BE5 /* Resources */,
|
||||||
@ -241,7 +206,6 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
DDC6FD45F59CD5AA33826D72 /* [CP] Check Pods Manifest.lock */,
|
|
||||||
33CC10E92044A3C60003C045 /* Sources */,
|
33CC10E92044A3C60003C045 /* Sources */,
|
||||||
33CC10EA2044A3C60003C045 /* Frameworks */,
|
33CC10EA2044A3C60003C045 /* Frameworks */,
|
||||||
33CC10EB2044A3C60003C045 /* Resources */,
|
33CC10EB2044A3C60003C045 /* Resources */,
|
||||||
@ -336,28 +300,6 @@
|
|||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
2D5E86AC9DD4210FFD8C9DE8 /* [CP] Check Pods Manifest.lock */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
|
||||||
"${PODS_ROOT}/Manifest.lock",
|
|
||||||
);
|
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
|
||||||
outputFileListPaths = (
|
|
||||||
);
|
|
||||||
outputPaths = (
|
|
||||||
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
@ -396,28 +338,6 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
||||||
};
|
};
|
||||||
DDC6FD45F59CD5AA33826D72 /* [CP] Check Pods Manifest.lock */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
|
||||||
"${PODS_ROOT}/Manifest.lock",
|
|
||||||
);
|
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
|
||||||
outputFileListPaths = (
|
|
||||||
);
|
|
||||||
outputPaths = (
|
|
||||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@ -435,6 +355,7 @@
|
|||||||
files = (
|
files = (
|
||||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
|
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
|
||||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
|
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
|
||||||
|
AABB001B1B1B1B1B1B1B /* NativePickerRegistrar.swift in Sources */,
|
||||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
|
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@ -469,7 +390,6 @@
|
|||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
331C80DB294CF71000263BE5 /* Debug */ = {
|
331C80DB294CF71000263BE5 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 881127F55C6D6CFE2534841B /* Pods-RunnerTests.debug.xcconfig */;
|
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
@ -484,7 +404,6 @@
|
|||||||
};
|
};
|
||||||
331C80DC294CF71000263BE5 /* Release */ = {
|
331C80DC294CF71000263BE5 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 4EB19377A730AE2C095D7A54 /* Pods-RunnerTests.release.xcconfig */;
|
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
@ -499,7 +418,6 @@
|
|||||||
};
|
};
|
||||||
331C80DD294CF71000263BE5 /* Profile */ = {
|
331C80DD294CF71000263BE5 /* Profile */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = A5398467BE6DA3EC050E790F /* Pods-RunnerTests.profile.xcconfig */;
|
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
@ -719,18 +637,19 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Developer ID Application";
|
CODE_SIGN_IDENTITY = "Developer ID Application";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = LD76P8L42W;
|
"DEVELOPMENT_TEAM[sdk=macosx*]" = LD76P8L42W;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
OTHER_CODE_SIGN_FLAGS = "--timestamp --options runtime";
|
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
|
OTHER_CODE_SIGN_FLAGS = "--timestamp --options runtime";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,4 +10,13 @@ class AppDelegate: FlutterAppDelegate {
|
|||||||
override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
|
override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func applicationDidFinishLaunching(_ notification: Notification) {
|
||||||
|
// Register our custom native picker that shows hidden files
|
||||||
|
// This is called before Flutter engine starts
|
||||||
|
if let controller = mainFlutterWindow?.contentViewController as? FlutterViewController {
|
||||||
|
NativePickerRegistrar.register(with: controller.registrar(forPlugin: "NativePickerRegistrar"))
|
||||||
|
}
|
||||||
|
super.applicationDidFinishLaunching(notification)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
84
macos/Runner/NativePickerRegistrar.swift
Normal file
84
macos/Runner/NativePickerRegistrar.swift
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import Cocoa
|
||||||
|
import FlutterMacOS
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
|
/// Registers a method channel for native file picking with hidden files visible.
|
||||||
|
/// Called from Dart via `ensureInitialized`.
|
||||||
|
class NativePickerRegistrar: NSObject, FlutterPlugin {
|
||||||
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||||
|
let channel = FlutterMethodChannel(
|
||||||
|
name: "com.svrnty.native_picker",
|
||||||
|
binaryMessenger: registrar.messenger)
|
||||||
|
let instance = NativePickerRegistrar()
|
||||||
|
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||||
|
switch call.method {
|
||||||
|
case "getDirectoryPath":
|
||||||
|
let args = call.arguments as? [String: Any] ?? [:]
|
||||||
|
let dialog = NSOpenPanel()
|
||||||
|
|
||||||
|
if let initial = args["initialDirectory"] as? String, !initial.isEmpty {
|
||||||
|
dialog.directoryURL = URL(fileURLWithPath: initial)
|
||||||
|
}
|
||||||
|
dialog.showsHiddenFiles = true
|
||||||
|
dialog.canChooseDirectories = true
|
||||||
|
dialog.canChooseFiles = false
|
||||||
|
dialog.allowsMultipleSelection = false
|
||||||
|
dialog.treatsFilePackagesAsDirectories = true
|
||||||
|
dialog.message = "Select a folder containing session files"
|
||||||
|
|
||||||
|
guard let window = NSApp.keyWindow else {
|
||||||
|
result(FlutterError(code: "NO_WINDOW", message: "No key window found", details: nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.beginSheetModal(for: window) { response in
|
||||||
|
if response == .OK, let url = dialog.url {
|
||||||
|
result(url.path)
|
||||||
|
} else {
|
||||||
|
result(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case "pickFiles":
|
||||||
|
let args = call.arguments as? [String: Any] ?? [:]
|
||||||
|
let dialog = NSOpenPanel()
|
||||||
|
|
||||||
|
if let initial = args["initialDirectory"] as? String, !initial.isEmpty {
|
||||||
|
dialog.directoryURL = URL(fileURLWithPath: initial)
|
||||||
|
}
|
||||||
|
dialog.showsHiddenFiles = true
|
||||||
|
dialog.canChooseDirectories = false
|
||||||
|
dialog.canChooseFiles = true
|
||||||
|
dialog.allowsMultipleSelection = false
|
||||||
|
|
||||||
|
if let extensions = args["allowedExtensions"] as? [String], !extensions.isEmpty {
|
||||||
|
if #available(macOS 11.0, *) {
|
||||||
|
let contentTypes = extensions.compactMap { UTType(filenameExtension: $0) }
|
||||||
|
dialog.allowedContentTypes = contentTypes
|
||||||
|
} else {
|
||||||
|
dialog.allowedFileTypes = extensions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialog.message = "Select a session file"
|
||||||
|
|
||||||
|
guard let window = NSApp.keyWindow else {
|
||||||
|
result(FlutterError(code: "NO_WINDOW", message: "No key window found", details: nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.beginSheetModal(for: window) { response in
|
||||||
|
if response == .OK, let url = dialog.url {
|
||||||
|
result([url.path])
|
||||||
|
} else {
|
||||||
|
result(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
result(FlutterMethodNotImplemented)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,11 +2,9 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.app-sandbox</key>
|
<key>com.apple.security.get-task-allow</key>
|
||||||
<true/>
|
<false/>
|
||||||
<key>com.apple.security.files.user-selected.read-only</key>
|
<key>com.apple.security.files.user-selected.read-only</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.files.home-directory.read-only</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user