docs: remove outdated metadata files and update README with new demo GIF
@@ -18,7 +18,9 @@
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/1.png" alt="App Demo" width="250" />
|
|
||||||
|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@@ -73,7 +75,7 @@ flutter run -d ios # or: -d android
|
|||||||
|
|
||||||
| | | | |
|
| | | | |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/2.png" alt="Screenshot 2" width="200" /> | <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/3.png" alt="Screenshot 3" width="200" /> | <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/4.png" alt="Screenshot 4" width="200" /> | <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/5.png" alt="Screenshot 5" width="200" /> |
|
| <img src="fastlane/metadata/en-US/images/phoneScreenshots/2.png" alt="Screenshot 2" width="200" /> | <img src="fastlane/metadata/en-US/images/phoneScreenshots/3.png" alt="Screenshot 3" width="200" /> | <img src="fastlane/metadata/en-US/images/phoneScreenshots/4.png" alt="Screenshot 4" width="200" /> | <img src="fastlane/metadata/en-US/images/phoneScreenshots/5.png" alt="Screenshot 5" width="200" /> |
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 25 KiB |
@@ -1,24 +0,0 @@
|
|||||||
Conduit is an open-source, native mobile client for Open‑WebUI. Connect to your own server to chat with AI models, manage conversations, and take your self‑hosted AI with you—securely and on the go.
|
|
||||||
|
|
||||||
Key Features
|
|
||||||
- Real-time streaming chat
|
|
||||||
- Model selection
|
|
||||||
- Conversation search and management
|
|
||||||
- Voice input (speech-to-text)
|
|
||||||
- File and image uploads for retrieval-augmented generation (RAG)
|
|
||||||
- Vision and multi‑modal support
|
|
||||||
- Markdown rendering with syntax highlighting
|
|
||||||
- Light, dark, and system themes
|
|
||||||
- Secure credential storage
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
- An existing Open‑WebUI server (Conduit does not host or provide AI models).
|
|
||||||
|
|
||||||
Privacy & Permissions
|
|
||||||
- Microphone: For voice input
|
|
||||||
- Camera and Photos: For image/file attachments
|
|
||||||
- Network: To connect to your Open‑WebUI server
|
|
||||||
|
|
||||||
Open Source
|
|
||||||
Built with Flutter and maintained by the community. Contributions are welcome.
|
|
||||||
|
|
||||||
BIN
fastlane/metadata/en-US/images/conduit-demo.gif
Normal file
|
After Width: | Height: | Size: 79 MiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 705 KiB After Width: | Height: | Size: 705 KiB |
|
Before Width: | Height: | Size: 387 KiB After Width: | Height: | Size: 387 KiB |
|
Before Width: | Height: | Size: 293 KiB After Width: | Height: | Size: 293 KiB |
|
Before Width: | Height: | Size: 568 KiB After Width: | Height: | Size: 568 KiB |
|
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 373 KiB |
|
Before Width: | Height: | Size: 977 KiB |
|
Before Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 341 KiB |
|
Before Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 256 KiB |
|
Before Width: | Height: | Size: 222 KiB |
@@ -1,2 +0,0 @@
|
|||||||
Conduit
|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Chat with your self‑hosted AI
|
|
||||||
|
|
||||||
@@ -483,7 +483,7 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
|
|||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
obscureText: _obscurePassword,
|
obscureText: _obscurePassword,
|
||||||
semanticLabel: 'Enter your API key',
|
semanticLabel: AppLocalizations.of(context)!.enterApiKey,
|
||||||
prefixIcon: Icon(
|
prefixIcon: Icon(
|
||||||
Platform.isIOS
|
Platform.isIOS
|
||||||
? CupertinoIcons.lock_shield
|
? CupertinoIcons.lock_shield
|
||||||
@@ -516,14 +516,14 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
|
|||||||
children: [
|
children: [
|
||||||
AccessibleFormField(
|
AccessibleFormField(
|
||||||
label: AppLocalizations.of(context)!.usernameOrEmail,
|
label: AppLocalizations.of(context)!.usernameOrEmail,
|
||||||
hint: 'Enter your username or email',
|
hint: AppLocalizations.of(context)!.usernameOrEmailHint,
|
||||||
controller: _usernameController,
|
controller: _usernameController,
|
||||||
validator: InputValidationService.combine([
|
validator: InputValidationService.combine([
|
||||||
InputValidationService.validateRequired,
|
InputValidationService.validateRequired,
|
||||||
(value) => InputValidationService.validateEmailOrUsername(value),
|
(value) => InputValidationService.validateEmailOrUsername(value),
|
||||||
]),
|
]),
|
||||||
keyboardType: TextInputType.emailAddress,
|
keyboardType: TextInputType.emailAddress,
|
||||||
semanticLabel: 'Enter your username or email',
|
semanticLabel: AppLocalizations.of(context)!.usernameOrEmailHint,
|
||||||
prefixIcon: Icon(
|
prefixIcon: Icon(
|
||||||
Platform.isIOS ? CupertinoIcons.person : Icons.person_outline,
|
Platform.isIOS ? CupertinoIcons.person : Icons.person_outline,
|
||||||
color: context.conduitTheme.iconSecondary,
|
color: context.conduitTheme.iconSecondary,
|
||||||
@@ -534,18 +534,18 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
|
|||||||
const SizedBox(height: Spacing.lg),
|
const SizedBox(height: Spacing.lg),
|
||||||
AccessibleFormField(
|
AccessibleFormField(
|
||||||
label: AppLocalizations.of(context)!.password,
|
label: AppLocalizations.of(context)!.password,
|
||||||
hint: 'Enter your password',
|
hint: AppLocalizations.of(context)!.passwordHint,
|
||||||
controller: _passwordController,
|
controller: _passwordController,
|
||||||
validator: InputValidationService.combine([
|
validator: InputValidationService.combine([
|
||||||
InputValidationService.validateRequired,
|
InputValidationService.validateRequired,
|
||||||
(value) => InputValidationService.validateMinLength(
|
(value) => InputValidationService.validateMinLength(
|
||||||
value,
|
value,
|
||||||
1,
|
1,
|
||||||
fieldName: 'Password',
|
fieldName: AppLocalizations.of(context)!.password,
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
obscureText: _obscurePassword,
|
obscureText: _obscurePassword,
|
||||||
semanticLabel: 'Enter your password',
|
semanticLabel: AppLocalizations.of(context)!.passwordHint,
|
||||||
prefixIcon: Icon(
|
prefixIcon: Icon(
|
||||||
Platform.isIOS ? CupertinoIcons.lock : Icons.lock_outline,
|
Platform.isIOS ? CupertinoIcons.lock : Icons.lock_outline,
|
||||||
color: context.conduitTheme.iconSecondary,
|
color: context.conduitTheme.iconSecondary,
|
||||||
@@ -576,7 +576,7 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
|
|||||||
child:
|
child:
|
||||||
ConduitButton(
|
ConduitButton(
|
||||||
text: _isSigningIn
|
text: _isSigningIn
|
||||||
? 'Signing in...'
|
? AppLocalizations.of(context)!.signingIn
|
||||||
: _useApiKey
|
: _useApiKey
|
||||||
? AppLocalizations.of(context)!.signInWithApiKey
|
? AppLocalizations.of(context)!.signInWithApiKey
|
||||||
: AppLocalizations.of(context)!.signIn,
|
: AppLocalizations.of(context)!.signIn,
|
||||||
|
|||||||
@@ -360,7 +360,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
|
|||||||
Positioned(
|
Positioned(
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
child: ConduitBadge(
|
child: ConduitBadge(
|
||||||
text: 'Demo',
|
text: AppLocalizations.of(context)!.demoBadge,
|
||||||
backgroundColor: context.conduitTheme.warning.withValues(alpha: 0.15),
|
backgroundColor: context.conduitTheme.warning.withValues(alpha: 0.15),
|
||||||
textColor: context.conduitTheme.warning,
|
textColor: context.conduitTheme.warning,
|
||||||
isCompact: true,
|
isCompact: true,
|
||||||
@@ -425,7 +425,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Demo Mode Active',
|
AppLocalizations.of(context)!.demoModeActive,
|
||||||
style: context.conduitTheme.bodyMedium?.copyWith(
|
style: context.conduitTheme.bodyMedium?.copyWith(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: context.conduitTheme.warning,
|
color: context.conduitTheme.warning,
|
||||||
@@ -433,7 +433,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: Spacing.xs),
|
const SizedBox(height: Spacing.xs),
|
||||||
Text(
|
Text(
|
||||||
'Skip server setup and try the demo',
|
AppLocalizations.of(context)!.skipServerSetupTryDemo,
|
||||||
style: context.conduitTheme.bodySmall?.copyWith(
|
style: context.conduitTheme.bodySmall?.copyWith(
|
||||||
color: context.conduitTheme.textSecondary,
|
color: context.conduitTheme.textSecondary,
|
||||||
),
|
),
|
||||||
@@ -445,7 +445,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: Spacing.lg),
|
const SizedBox(height: Spacing.lg),
|
||||||
ConduitButton(
|
ConduitButton(
|
||||||
text: 'Enter Demo',
|
text: AppLocalizations.of(context)!.enterDemo,
|
||||||
icon: Platform.isIOS ? CupertinoIcons.play_fill : Icons.play_arrow,
|
icon: Platform.isIOS ? CupertinoIcons.play_fill : Icons.play_arrow,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
@@ -470,15 +470,15 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
AccessibleFormField(
|
AccessibleFormField(
|
||||||
label: 'Server URL',
|
label: AppLocalizations.of(context)!.serverUrl,
|
||||||
hint: 'https://your-server.com',
|
hint: AppLocalizations.of(context)!.serverUrlHint,
|
||||||
controller: _urlController,
|
controller: _urlController,
|
||||||
validator: InputValidationService.combine([
|
validator: InputValidationService.combine([
|
||||||
InputValidationService.validateRequired,
|
InputValidationService.validateRequired,
|
||||||
(value) => InputValidationService.validateUrl(value, required: true),
|
(value) => InputValidationService.validateUrl(value, required: true),
|
||||||
]),
|
]),
|
||||||
keyboardType: TextInputType.url,
|
keyboardType: TextInputType.url,
|
||||||
semanticLabel: 'Enter your server URL or IP address',
|
semanticLabel: AppLocalizations.of(context)!.enterServerUrlSemantic,
|
||||||
onSubmitted: (_) => _connectToServer(),
|
onSubmitted: (_) => _connectToServer(),
|
||||||
prefixIcon: Icon(
|
prefixIcon: Icon(
|
||||||
Platform.isIOS ? CupertinoIcons.globe : Icons.public,
|
Platform.isIOS ? CupertinoIcons.globe : Icons.public,
|
||||||
@@ -533,7 +533,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Advanced Settings',
|
AppLocalizations.of(context)!.advancedSettings,
|
||||||
style: context.conduitTheme.bodyMedium?.copyWith(
|
style: context.conduitTheme.bodyMedium?.copyWith(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
@@ -582,7 +582,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Custom Headers',
|
AppLocalizations.of(context)!.customHeaders,
|
||||||
style: context.conduitTheme.bodyMedium?.copyWith(
|
style: context.conduitTheme.bodyMedium?.copyWith(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
@@ -600,7 +600,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: Spacing.xs),
|
const SizedBox(height: Spacing.xs),
|
||||||
Text(
|
Text(
|
||||||
'Add custom HTTP headers for authentication, API keys, or special server requirements.',
|
AppLocalizations.of(context)!.customHeadersDescription,
|
||||||
style: context.conduitTheme.bodySmall?.copyWith(
|
style: context.conduitTheme.bodySmall?.copyWith(
|
||||||
color: context.conduitTheme.textSecondary,
|
color: context.conduitTheme.textSecondary,
|
||||||
),
|
),
|
||||||
@@ -787,13 +787,13 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
|
|||||||
|
|
||||||
// Check for duplicates
|
// Check for duplicates
|
||||||
if (_customHeaders.containsKey(key)) {
|
if (_customHeaders.containsKey(key)) {
|
||||||
_showHeaderError('Header "$key" already exists. Remove it first to update.');
|
_showHeaderError(AppLocalizations.of(context)!.headerAlreadyExists(key));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check header count limit
|
// Check header count limit
|
||||||
if (_customHeaders.length >= 10) {
|
if (_customHeaders.length >= 10) {
|
||||||
_showHeaderError('Maximum of 10 custom headers allowed. Remove some to add more.');
|
_showHeaderError(AppLocalizations.of(context)!.maxHeadersReachedDetail);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -807,47 +807,47 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
|
|||||||
|
|
||||||
String? _validateHeaderKey(String key) {
|
String? _validateHeaderKey(String key) {
|
||||||
// RFC 7230 compliant header name validation
|
// RFC 7230 compliant header name validation
|
||||||
if (key.isEmpty) return 'Header name cannot be empty';
|
if (key.isEmpty) return AppLocalizations.of(context)!.headerNameEmpty;
|
||||||
if (key.length > 64) return 'Header name too long (max 64 characters)';
|
if (key.length > 64) return AppLocalizations.of(context)!.headerNameTooLong;
|
||||||
|
|
||||||
// Check for valid characters (RFC 7230: token characters)
|
// Check for valid characters (RFC 7230: token characters)
|
||||||
if (!RegExp(r'^[a-zA-Z0-9!#$&\-^_`|~]+$').hasMatch(key)) {
|
if (!RegExp(r'^[a-zA-Z0-9!#$&\-^_`|~]+$').hasMatch(key)) {
|
||||||
return 'Invalid header name. Use only letters, numbers, and these symbols: !#\$&-^_`|~';
|
return AppLocalizations.of(context)!.headerNameInvalidChars;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for reserved headers that should not be overridden
|
// Check for reserved headers that should not be overridden
|
||||||
final lowerKey = key.toLowerCase();
|
final lowerKey = key.toLowerCase();
|
||||||
final reservedHeaders = {
|
final reservedHeaders = {
|
||||||
'authorization', 'content-type', 'content-length', 'host',
|
'authorization', 'content-type', 'content-length', 'host',
|
||||||
'user-agent', 'accept', 'accept-encoding', 'connection',
|
'user-agent', 'accept', 'accept-encoding', 'connection',
|
||||||
'transfer-encoding', 'upgrade', 'via', 'warning'
|
'transfer-encoding', 'upgrade', 'via', 'warning'
|
||||||
};
|
};
|
||||||
|
|
||||||
if (reservedHeaders.contains(lowerKey)) {
|
if (reservedHeaders.contains(lowerKey)) {
|
||||||
return 'Cannot override reserved header "$key"';
|
return AppLocalizations.of(context)!.headerNameReserved(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String? _validateHeaderValue(String value) {
|
String? _validateHeaderValue(String value) {
|
||||||
if (value.isEmpty) return 'Header value cannot be empty';
|
if (value.isEmpty) return AppLocalizations.of(context)!.headerValueEmpty;
|
||||||
if (value.length > 1024) return 'Header value too long (max 1024 characters)';
|
if (value.length > 1024) return AppLocalizations.of(context)!.headerValueTooLong;
|
||||||
|
|
||||||
// Check for valid characters (no control characters except tab)
|
// Check for valid characters (no control characters except tab)
|
||||||
for (int i = 0; i < value.length; i++) {
|
for (int i = 0; i < value.length; i++) {
|
||||||
final char = value.codeUnitAt(i);
|
final char = value.codeUnitAt(i);
|
||||||
// Allow printable ASCII (32-126) and tab (9)
|
// Allow printable ASCII (32-126) and tab (9)
|
||||||
if (char != 9 && (char < 32 || char > 126)) {
|
if (char != 9 && (char < 32 || char > 126)) {
|
||||||
return 'Header value contains invalid characters. Use only printable ASCII.';
|
return AppLocalizations.of(context)!.headerValueInvalidChars;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for security-sensitive patterns
|
// Check for security-sensitive patterns
|
||||||
if (value.toLowerCase().contains('script') ||
|
if (value.toLowerCase().contains('script') ||
|
||||||
value.contains('<') ||
|
value.contains('<') ||
|
||||||
value.contains('>')) {
|
value.contains('>')) {
|
||||||
return 'Header value appears to contain potentially unsafe content';
|
return AppLocalizations.of(context)!.headerValueUnsafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -404,19 +404,43 @@ abstract class AppLocalizations {
|
|||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Username or Email'**
|
/// **'Username or Email'**
|
||||||
String get usernameOrEmail;
|
String get usernameOrEmail;
|
||||||
|
|
||||||
/// No description provided for @password.
|
/// No description provided for @password.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Password'**
|
/// **'Password'**
|
||||||
String get password;
|
String get password;
|
||||||
|
|
||||||
|
/// No description provided for @usernameOrEmailHint.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Enter your username or email'**
|
||||||
|
String get usernameOrEmailHint;
|
||||||
|
|
||||||
|
/// No description provided for @passwordHint.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Enter your password'**
|
||||||
|
String get passwordHint;
|
||||||
|
|
||||||
/// No description provided for @signInWithApiKey.
|
/// No description provided for @signInWithApiKey.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Sign in with API Key'**
|
/// **'Sign in with API Key'**
|
||||||
String get signInWithApiKey;
|
String get signInWithApiKey;
|
||||||
|
|
||||||
|
/// No description provided for @enterApiKey.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Enter your API key'**
|
||||||
|
String get enterApiKey;
|
||||||
|
|
||||||
|
/// No description provided for @signingIn.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Signing in...'**
|
||||||
|
String get signingIn;
|
||||||
|
|
||||||
/// No description provided for @connectToServer.
|
/// No description provided for @connectToServer.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -483,6 +507,84 @@ abstract class AppLocalizations {
|
|||||||
/// **'Remove header'**
|
/// **'Remove header'**
|
||||||
String get removeHeader;
|
String get removeHeader;
|
||||||
|
|
||||||
|
/// No description provided for @advancedSettings.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Advanced Settings'**
|
||||||
|
String get advancedSettings;
|
||||||
|
|
||||||
|
/// No description provided for @customHeaders.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Custom Headers'**
|
||||||
|
String get customHeaders;
|
||||||
|
|
||||||
|
/// No description provided for @customHeadersDescription.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Add custom HTTP headers for authentication, API keys, or special server requirements.'**
|
||||||
|
String get customHeadersDescription;
|
||||||
|
|
||||||
|
/// No description provided for @headerNameEmpty.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Header name cannot be empty'**
|
||||||
|
String get headerNameEmpty;
|
||||||
|
|
||||||
|
/// No description provided for @headerNameTooLong.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Header name too long (max 64 characters)'**
|
||||||
|
String get headerNameTooLong;
|
||||||
|
|
||||||
|
/// No description provided for @headerNameInvalidChars.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Invalid header name. Use only letters, numbers, and these symbols: !#\$&-^_`|~'**
|
||||||
|
String get headerNameInvalidChars;
|
||||||
|
|
||||||
|
/// No description provided for @headerNameReserved.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Cannot override reserved header "{key}"'**
|
||||||
|
String headerNameReserved(String key);
|
||||||
|
|
||||||
|
/// No description provided for @headerValueEmpty.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Header value cannot be empty'**
|
||||||
|
String get headerValueEmpty;
|
||||||
|
|
||||||
|
/// No description provided for @headerValueTooLong.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Header value too long (max 1024 characters)'**
|
||||||
|
String get headerValueTooLong;
|
||||||
|
|
||||||
|
/// No description provided for @headerValueInvalidChars.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Header value contains invalid characters. Use only printable ASCII.'**
|
||||||
|
String get headerValueInvalidChars;
|
||||||
|
|
||||||
|
/// No description provided for @headerValueUnsafe.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Header value appears to contain potentially unsafe content'**
|
||||||
|
String get headerValueUnsafe;
|
||||||
|
|
||||||
|
/// No description provided for @headerAlreadyExists.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Header "{key}" already exists. Remove it first to update.'**
|
||||||
|
String headerAlreadyExists(String key);
|
||||||
|
|
||||||
|
/// No description provided for @maxHeadersReachedDetail.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Maximum of 10 custom headers allowed. Remove some to add more.'**
|
||||||
|
String get maxHeadersReachedDetail;
|
||||||
|
|
||||||
/// No description provided for @connecting.
|
/// No description provided for @connecting.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -177,9 +177,21 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get password => 'Passwort';
|
String get password => 'Passwort';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get usernameOrEmailHint => 'Gib deinen Benutzernamen oder deine E‑Mail ein';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get passwordHint => 'Gib dein Passwort ein';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get signInWithApiKey => 'Mit API-Schlüssel anmelden';
|
String get signInWithApiKey => 'Mit API-Schlüssel anmelden';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get enterApiKey => 'Gib deinen API-Schlüssel ein';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get signingIn => 'Anmeldung läuft...';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get connectToServer => 'Mit Server verbinden';
|
String get connectToServer => 'Mit Server verbinden';
|
||||||
|
|
||||||
@@ -213,6 +225,51 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get removeHeader => 'Header entfernen';
|
String get removeHeader => 'Header entfernen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get advancedSettings => 'Erweiterte Einstellungen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get customHeaders => 'Benutzerdefinierte Header';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get customHeadersDescription =>
|
||||||
|
'Füge benutzerdefinierte HTTP-Header für Authentifizierung, API-Schlüssel oder spezielle Serveranforderungen hinzu.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameEmpty => 'Header-Name darf nicht leer sein';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameTooLong => 'Header-Name zu lang (max. 64 Zeichen)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameInvalidChars =>
|
||||||
|
'Ungültiger Header-Name. Verwende nur Buchstaben, Zahlen und diese Symbole: !#\$&-^_`|~';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String headerNameReserved(String key) => 'Reservierter Header "$key" kann nicht überschrieben werden';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueEmpty => 'Header-Wert darf nicht leer sein';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueTooLong => 'Header-Wert zu lang (max. 1024 Zeichen)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueInvalidChars =>
|
||||||
|
'Header-Wert enthält ungültige Zeichen. Verwende nur druckbare ASCII-Zeichen.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueUnsafe =>
|
||||||
|
'Header-Wert scheint potenziell unsicheren Inhalt zu enthalten';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String headerAlreadyExists(String key) =>
|
||||||
|
'Header "$key" existiert bereits. Entferne ihn zuerst, um ihn zu aktualisieren.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get maxHeadersReachedDetail =>
|
||||||
|
'Maximal 10 benutzerdefinierte Header erlaubt. Entferne einige, um weitere hinzuzufügen.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get connecting => 'Verbindung wird hergestellt...';
|
String get connecting => 'Verbindung wird hergestellt...';
|
||||||
|
|
||||||
|
|||||||
@@ -177,9 +177,21 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get password => 'Password';
|
String get password => 'Password';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get usernameOrEmailHint => 'Enter your username or email';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get passwordHint => 'Enter your password';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get signInWithApiKey => 'Sign in with API Key';
|
String get signInWithApiKey => 'Sign in with API Key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get enterApiKey => 'Enter your API key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get signingIn => 'Signing in...';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get connectToServer => 'Connect to Server';
|
String get connectToServer => 'Connect to Server';
|
||||||
|
|
||||||
@@ -213,6 +225,51 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get removeHeader => 'Remove header';
|
String get removeHeader => 'Remove header';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get advancedSettings => 'Advanced Settings';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get customHeaders => 'Custom Headers';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get customHeadersDescription =>
|
||||||
|
'Add custom HTTP headers for authentication, API keys, or special server requirements.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameEmpty => 'Header name cannot be empty';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameTooLong => 'Header name too long (max 64 characters)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameInvalidChars =>
|
||||||
|
'Invalid header name. Use only letters, numbers, and these symbols: !#\$&-^_`|~';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String headerNameReserved(String key) => 'Cannot override reserved header "$key"';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueEmpty => 'Header value cannot be empty';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueTooLong => 'Header value too long (max 1024 characters)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueInvalidChars =>
|
||||||
|
'Header value contains invalid characters. Use only printable ASCII.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueUnsafe =>
|
||||||
|
'Header value appears to contain potentially unsafe content';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String headerAlreadyExists(String key) =>
|
||||||
|
'Header "$key" already exists. Remove it first to update.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get maxHeadersReachedDetail =>
|
||||||
|
'Maximum of 10 custom headers allowed. Remove some to add more.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get connecting => 'Connecting...';
|
String get connecting => 'Connecting...';
|
||||||
|
|
||||||
|
|||||||
@@ -177,9 +177,21 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get password => 'Mot de passe';
|
String get password => 'Mot de passe';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get usernameOrEmailHint => 'Entrez votre nom d\'utilisateur ou e‑mail';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get passwordHint => 'Entrez votre mot de passe';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get signInWithApiKey => 'Se connecter avec une clé API';
|
String get signInWithApiKey => 'Se connecter avec une clé API';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get enterApiKey => 'Entrez votre clé API';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get signingIn => 'Connexion en cours...';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get connectToServer => 'Se connecter au serveur';
|
String get connectToServer => 'Se connecter au serveur';
|
||||||
|
|
||||||
@@ -213,6 +225,53 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get removeHeader => 'Supprimer l\'en-tête';
|
String get removeHeader => 'Supprimer l\'en-tête';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get advancedSettings => 'Paramètres avancés';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get customHeaders => 'En-têtes personnalisés';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get customHeadersDescription =>
|
||||||
|
'Ajoutez des en-têtes HTTP personnalisés pour l\'authentification, les clés API ou des exigences spécifiques du serveur.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameEmpty => 'Le nom de l\'en-tête ne peut pas être vide';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameTooLong => 'Nom d\'en-tête trop long (max 64 caractères)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameInvalidChars =>
|
||||||
|
'Nom d\'en-tête invalide. Utilisez uniquement des lettres, des chiffres et ces symboles : !#\$&-^_`|~';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String headerNameReserved(String key) =>
|
||||||
|
'Impossible d\'écraser l\'en-tête réservé « $key »';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueEmpty => 'La valeur de l\'en-tête ne peut pas être vide';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueTooLong =>
|
||||||
|
'Valeur d\'en-tête trop longue (max 1024 caractères)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueInvalidChars =>
|
||||||
|
'La valeur de l\'en-tête contient des caractères invalides. Utilisez uniquement des caractères ASCII imprimables.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueUnsafe =>
|
||||||
|
'La valeur de l\'en-tête semble contenir du contenu potentiellement dangereux';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String headerAlreadyExists(String key) =>
|
||||||
|
'L\'en-tête « $key » existe déjà. Supprimez-le d\'abord pour le modifier.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get maxHeadersReachedDetail =>
|
||||||
|
'Maximum 10 en-têtes personnalisés. Supprimez-en pour en ajouter.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get connecting => 'Connexion en cours...';
|
String get connecting => 'Connexion en cours...';
|
||||||
|
|
||||||
|
|||||||
@@ -177,9 +177,21 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get password => 'Password';
|
String get password => 'Password';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get usernameOrEmailHint => 'Inserisci il tuo username o e‑mail';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get passwordHint => 'Inserisci la password';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get signInWithApiKey => 'Accedi con chiave API';
|
String get signInWithApiKey => 'Accedi con chiave API';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get enterApiKey => 'Inserisci la tua chiave API';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get signingIn => 'Accesso in corso...';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get connectToServer => 'Connetti al server';
|
String get connectToServer => 'Connetti al server';
|
||||||
|
|
||||||
@@ -213,6 +225,52 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get removeHeader => 'Rimuovi header';
|
String get removeHeader => 'Rimuovi header';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get advancedSettings => 'Impostazioni avanzate';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get customHeaders => 'Header personalizzati';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get customHeadersDescription =>
|
||||||
|
'Aggiungi header HTTP personalizzati per autenticazione, chiavi API o requisiti speciali del server.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameEmpty => 'Il nome header non può essere vuoto';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameTooLong => 'Nome header troppo lungo (max 64 caratteri)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerNameInvalidChars =>
|
||||||
|
'Nome header non valido. Usa solo lettere, numeri e questi simboli: !#\$&-^_`|~';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String headerNameReserved(String key) =>
|
||||||
|
'Impossibile sovrascrivere l\'header riservato "$key"';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueEmpty => 'Il valore header non può essere vuoto';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueTooLong => 'Valore header troppo lungo (max 1024 caratteri)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueInvalidChars =>
|
||||||
|
'Il valore header contiene caratteri non validi. Usa solo ASCII stampabile.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get headerValueUnsafe =>
|
||||||
|
'Il valore header sembra contenere contenuto potenzialmente non sicuro';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String headerAlreadyExists(String key) =>
|
||||||
|
'L\'header "$key" esiste già. Rimuovilo prima per aggiornarlo.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get maxHeadersReachedDetail =>
|
||||||
|
'Massimo 10 header personalizzati consentiti. Rimuovine alcuni per aggiungerne altri.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get connecting => 'Connessione in corso...';
|
String get connecting => 'Connessione in corso...';
|
||||||
|
|
||||||
|
|||||||