mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:27:09 -05:00 
			
		
		
		
	* feat(mobile): use Weblate for i18n (2) * remove old translation files * dedup keys * remove migration report * chore * remove localizely.yml
		
			
				
	
	
		
			184 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'dart:convert';
 | 
						|
 | 
						|
import 'package:auto_route/auto_route.dart';
 | 
						|
import 'package:easy_localization/easy_localization.dart';
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
 | 
						|
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
						|
import 'package:immich_mobile/domain/models/store.model.dart';
 | 
						|
import 'package:immich_mobile/entities/store.entity.dart';
 | 
						|
 | 
						|
class SettingsHeader {
 | 
						|
  String key = "";
 | 
						|
  String value = "";
 | 
						|
}
 | 
						|
 | 
						|
@RoutePage()
 | 
						|
class HeaderSettingsPage extends HookConsumerWidget {
 | 
						|
  const HeaderSettingsPage({super.key});
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context, WidgetRef ref) {
 | 
						|
    // final apiService = ref.watch(apiServiceProvider);
 | 
						|
    final headers = useState<List<SettingsHeader>>([]);
 | 
						|
    final setInitialHeaders = useState(false);
 | 
						|
 | 
						|
    var headersStr = Store.get(StoreKey.customHeaders, "");
 | 
						|
    if (!setInitialHeaders.value) {
 | 
						|
      if (headersStr.isNotEmpty) {
 | 
						|
        var customHeaders = jsonDecode(headersStr) as Map;
 | 
						|
        customHeaders.forEach((k, v) {
 | 
						|
          final header = SettingsHeader();
 | 
						|
          header.key = k;
 | 
						|
          header.value = v;
 | 
						|
          headers.value.add(header);
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      // add first one to help the user
 | 
						|
      if (headers.value.isEmpty) {
 | 
						|
        final header = SettingsHeader();
 | 
						|
        header.key = '';
 | 
						|
        header.value = '';
 | 
						|
 | 
						|
        headers.value.add(header);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    setInitialHeaders.value = true;
 | 
						|
 | 
						|
    var list = [
 | 
						|
      ...headers.value.map((headerValue) {
 | 
						|
        return HeaderKeyValueSettings(
 | 
						|
          header: headerValue,
 | 
						|
          onRemove: () {
 | 
						|
            headers.value.remove(headerValue);
 | 
						|
            headers.value = headers.value.toList();
 | 
						|
          },
 | 
						|
        );
 | 
						|
      }),
 | 
						|
    ];
 | 
						|
 | 
						|
    return Scaffold(
 | 
						|
      appBar: AppBar(
 | 
						|
        title: const Text('advanced_settings_proxy_headers_title').tr(),
 | 
						|
        centerTitle: false,
 | 
						|
        actions: [
 | 
						|
          IconButton(
 | 
						|
            onPressed: () {
 | 
						|
              headers.value.add(SettingsHeader());
 | 
						|
              headers.value = headers.value.toList();
 | 
						|
            },
 | 
						|
            icon: const Icon(Icons.add_outlined),
 | 
						|
            tooltip: 'header_settings_add_header_tip'.tr(),
 | 
						|
          ),
 | 
						|
        ],
 | 
						|
      ),
 | 
						|
      body: PopScope(
 | 
						|
        onPopInvokedWithResult: (didPop, _) => saveHeaders(headers.value),
 | 
						|
        child: ListView.separated(
 | 
						|
          padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0),
 | 
						|
          itemCount: list.length,
 | 
						|
          itemBuilder: (ctx, index) => list[index],
 | 
						|
          separatorBuilder: (context, index) => const Padding(
 | 
						|
            padding: EdgeInsets.only(bottom: 16.0, left: 8, right: 8),
 | 
						|
            child: Divider(),
 | 
						|
          ),
 | 
						|
        ),
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  saveHeaders(List<SettingsHeader> headers) {
 | 
						|
    final headersMap = {};
 | 
						|
    for (var header in headers) {
 | 
						|
      final key = header.key.trim();
 | 
						|
      final value = header.value.trim();
 | 
						|
 | 
						|
      if (key.isEmpty || value.isEmpty) continue;
 | 
						|
      headersMap[key] = value;
 | 
						|
    }
 | 
						|
 | 
						|
    var encoded = jsonEncode(headersMap);
 | 
						|
    Store.put(StoreKey.customHeaders, encoded);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class HeaderKeyValueSettings extends StatelessWidget {
 | 
						|
  final TextEditingController keyController;
 | 
						|
  final TextEditingController valueController;
 | 
						|
  final SettingsHeader header;
 | 
						|
  final Function() onRemove;
 | 
						|
 | 
						|
  HeaderKeyValueSettings({
 | 
						|
    super.key,
 | 
						|
    required this.header,
 | 
						|
    required this.onRemove,
 | 
						|
  })  : keyController = TextEditingController(text: header.key),
 | 
						|
        valueController = TextEditingController(text: header.value);
 | 
						|
 | 
						|
  String? emptyFieldValidator(String? value) {
 | 
						|
    if (value == null || value.isEmpty) {
 | 
						|
      return 'header_settings_field_validator_msg'.tr();
 | 
						|
    }
 | 
						|
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    return Column(
 | 
						|
      children: [
 | 
						|
        Padding(
 | 
						|
          padding: const EdgeInsets.only(left: 8, right: 8, bottom: 12.0),
 | 
						|
          child: Row(
 | 
						|
            children: [
 | 
						|
              Expanded(
 | 
						|
                child: TextFormField(
 | 
						|
                  controller: keyController,
 | 
						|
                  decoration: InputDecoration(
 | 
						|
                    labelText: 'header_settings_header_name_input'.tr(),
 | 
						|
                    border: const OutlineInputBorder(),
 | 
						|
                  ),
 | 
						|
                  autocorrect: false,
 | 
						|
                  onChanged: (headerKey) {
 | 
						|
                    header.key = headerKey;
 | 
						|
                  },
 | 
						|
                  validator: emptyFieldValidator,
 | 
						|
                  textInputAction: TextInputAction.next,
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
              Padding(
 | 
						|
                padding: const EdgeInsets.only(left: 8),
 | 
						|
                child: IconButton(
 | 
						|
                  style: ElevatedButton.styleFrom(
 | 
						|
                    padding: const EdgeInsets.symmetric(vertical: 12),
 | 
						|
                  ),
 | 
						|
                  color: Colors.red[400],
 | 
						|
                  onPressed: onRemove,
 | 
						|
                  icon: const Icon(Icons.delete_outline),
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
            ],
 | 
						|
          ),
 | 
						|
        ),
 | 
						|
        Padding(
 | 
						|
          padding: const EdgeInsets.only(left: 8, right: 8, bottom: 12.0),
 | 
						|
          child: TextFormField(
 | 
						|
            controller: valueController,
 | 
						|
            decoration: InputDecoration(
 | 
						|
              labelText: 'header_settings_header_value_input'.tr(),
 | 
						|
              border: const OutlineInputBorder(),
 | 
						|
            ),
 | 
						|
            autocorrect: false,
 | 
						|
            onChanged: (headerValue) {
 | 
						|
              header.value = headerValue;
 | 
						|
            },
 | 
						|
            validator: emptyFieldValidator,
 | 
						|
            textInputAction: TextInputAction.done,
 | 
						|
          ),
 | 
						|
        ),
 | 
						|
      ],
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |