Skip to content

Commit 245fd14

Browse files
committed
Fix Cancel button missing in ConnectGitHubDialog after step 0
1 parent 66210aa commit 245fd14

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+14511
-51
lines changed

LocalizationManager.Core/Abstractions/IResourceWriter.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,12 @@ Task CreateLanguageFileAsync(
6464
/// <param name="language">Language information for the file to delete.</param>
6565
/// <param name="ct">Cancellation token.</param>
6666
Task DeleteLanguageFileAsync(LanguageInfo language, CancellationToken ct = default);
67+
68+
/// <summary>
69+
/// Serialize a ResourceFile to a string without writing to disk.
70+
/// Useful for API responses and GitHub sync operations.
71+
/// </summary>
72+
/// <param name="file">Resource file to serialize.</param>
73+
/// <returns>Serialized content as a string.</returns>
74+
string SerializeToString(ResourceFile file);
6775
}

LocalizationManager.Core/Backends/Android/AndroidResourceWriter.cs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,26 @@ public void Write(ResourceFile file)
4343
if (string.IsNullOrEmpty(file.Language.FilePath))
4444
throw new ArgumentException("Language file path is required");
4545

46+
var doc = BuildXmlDocument(file);
47+
48+
// Save with proper formatting
49+
var settings = new XmlWriterSettings
50+
{
51+
Indent = true,
52+
IndentChars = " ",
53+
Encoding = new UTF8Encoding(false),
54+
OmitXmlDeclaration = false
55+
};
56+
57+
using var writer = XmlWriter.Create(file.Language.FilePath, settings);
58+
doc.Save(writer);
59+
}
60+
61+
/// <summary>
62+
/// Builds the XDocument from the resource file.
63+
/// </summary>
64+
private XDocument BuildXmlDocument(ResourceFile file)
65+
{
4666
var doc = new XDocument(
4767
new XDeclaration("1.0", "utf-8", null),
4868
new XElement("resources")
@@ -92,17 +112,7 @@ public void Write(ResourceFile file)
92112
}
93113
}
94114

95-
// Save with proper formatting
96-
var settings = new XmlWriterSettings
97-
{
98-
Indent = true,
99-
IndentChars = " ",
100-
Encoding = new UTF8Encoding(false),
101-
OmitXmlDeclaration = false
102-
};
103-
104-
using var writer = XmlWriter.Create(file.Language.FilePath, settings);
105-
doc.Save(writer);
115+
return doc;
106116
}
107117

108118
/// <inheritdoc />
@@ -181,6 +191,25 @@ public Task DeleteLanguageFileAsync(LanguageInfo language, CancellationToken ct
181191
return Task.CompletedTask;
182192
}
183193

194+
/// <inheritdoc />
195+
public string SerializeToString(ResourceFile file)
196+
{
197+
var doc = BuildXmlDocument(file);
198+
var settings = new XmlWriterSettings
199+
{
200+
Indent = true,
201+
IndentChars = " ",
202+
Encoding = new UTF8Encoding(false),
203+
OmitXmlDeclaration = false
204+
};
205+
206+
using var stringWriter = new StringWriter();
207+
using var writer = XmlWriter.Create(stringWriter, settings);
208+
doc.Save(writer);
209+
writer.Flush();
210+
return stringWriter.ToString();
211+
}
212+
184213
/// <summary>
185214
/// Writes a string element.
186215
/// </summary>

LocalizationManager.Core/Backends/Json/JsonResourceWriter.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ public JsonResourceWriter(JsonFormatConfiguration? config = null)
4545

4646
/// <inheritdoc />
4747
public void Write(ResourceFile file)
48+
{
49+
var json = BuildJsonString(file);
50+
File.WriteAllText(file.Language.FilePath, json);
51+
}
52+
53+
/// <summary>
54+
/// Builds the JSON string from the resource file without writing to disk.
55+
/// </summary>
56+
private string BuildJsonString(ResourceFile file)
4857
{
4958
var root = new Dictionary<string, object>();
5059

@@ -96,13 +105,11 @@ public void Write(ResourceFile file)
96105
}
97106
}
98107

99-
var json = JsonSerializer.Serialize(root, new JsonSerializerOptions
108+
return JsonSerializer.Serialize(root, new JsonSerializerOptions
100109
{
101110
WriteIndented = true,
102111
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
103112
});
104-
105-
File.WriteAllText(file.Language.FilePath, json);
106113
}
107114

108115
/// <inheritdoc />
@@ -174,6 +181,12 @@ public Task DeleteLanguageFileAsync(LanguageInfo language, CancellationToken ct
174181
return Task.CompletedTask;
175182
}
176183

184+
/// <inheritdoc />
185+
public string SerializeToString(ResourceFile file)
186+
{
187+
return BuildJsonString(file);
188+
}
189+
177190
/// <summary>
178191
/// Creates the appropriate value representation for a resource entry.
179192
/// </summary>

LocalizationManager.Core/Backends/Resx/ResxResourceWriter.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2020
// SOFTWARE.
2121

22+
using System.Xml.Linq;
2223
using LocalizationManager.Core.Abstractions;
2324
using LocalizationManager.Core.Models;
2425

@@ -63,4 +64,54 @@ public Task DeleteLanguageFileAsync(LanguageInfo language, CancellationToken ct
6364
_fileManager.DeleteLanguageFile(language);
6465
return Task.CompletedTask;
6566
}
67+
68+
/// <inheritdoc />
69+
public string SerializeToString(ResourceFile file)
70+
{
71+
var xdoc = CreateNewResxDocument();
72+
var root = xdoc.Root!;
73+
74+
foreach (var entry in file.Entries)
75+
{
76+
root.Add(CreateDataElement(entry));
77+
}
78+
79+
return xdoc.Declaration + Environment.NewLine + xdoc.ToString();
80+
}
81+
82+
private static XDocument CreateNewResxDocument()
83+
{
84+
return new XDocument(
85+
new XDeclaration("1.0", "utf-8", null),
86+
new XElement("root",
87+
new XElement("resheader",
88+
new XAttribute("name", "resmimetype"),
89+
new XElement("value", "text/microsoft-resx")),
90+
new XElement("resheader",
91+
new XAttribute("name", "version"),
92+
new XElement("value", "2.0")),
93+
new XElement("resheader",
94+
new XAttribute("name", "reader"),
95+
new XElement("value", "System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")),
96+
new XElement("resheader",
97+
new XAttribute("name", "writer"),
98+
new XElement("value", "System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"))
99+
)
100+
);
101+
}
102+
103+
private static XElement CreateDataElement(ResourceEntry entry)
104+
{
105+
var dataElement = new XElement("data",
106+
new XAttribute("name", entry.Key),
107+
new XAttribute(XNamespace.Xml + "space", "preserve"),
108+
new XElement("value", entry.Value ?? string.Empty));
109+
110+
if (!string.IsNullOrEmpty(entry.Comment))
111+
{
112+
dataElement.Add(new XElement("comment", entry.Comment));
113+
}
114+
115+
return dataElement;
116+
}
66117
}

LocalizationManager.Core/Backends/iOS/IosResourceWriter.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,46 @@ public Task DeleteLanguageFileAsync(LanguageInfo language, CancellationToken ct
168168
return Task.CompletedTask;
169169
}
170170

171+
/// <inheritdoc />
172+
public string SerializeToString(ResourceFile file)
173+
{
174+
// For iOS, we serialize to .strings format (simple strings only)
175+
// Plurals would need to be in a separate .stringsdict file
176+
var simpleStrings = file.Entries.Where(e => !e.IsPlural).ToList();
177+
178+
if (!simpleStrings.Any())
179+
{
180+
return "";
181+
}
182+
183+
var stringsEntries = simpleStrings.Select(e =>
184+
new StringsFileParser.StringsEntry(e.Key, e.Value ?? "", e.Comment));
185+
186+
return _stringsParser.Serialize(stringsEntries);
187+
}
188+
189+
/// <summary>
190+
/// Serialize entries to .stringsdict format (for plurals).
191+
/// </summary>
192+
public string SerializeToStringdict(ResourceFile file)
193+
{
194+
var pluralStrings = file.Entries.Where(e => e.IsPlural && e.PluralForms?.Count > 0).ToList();
195+
196+
if (!pluralStrings.Any())
197+
{
198+
return "";
199+
}
200+
201+
var stringsdictEntries = pluralStrings.Select(e =>
202+
new StringsdictParser.StringsdictEntry(
203+
e.Key,
204+
StringsdictParser.CreateFormatKey(),
205+
DetectValueType(e.PluralForms!),
206+
e.PluralForms!));
207+
208+
return _stringsdictParser.Serialize(stringsdictEntries);
209+
}
210+
171211
/// <summary>
172212
/// Detects the value type from plural forms (d for integers, f for floats, @ for objects).
173213
/// </summary>

cloud/deploy/config.sample.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
"apiKeyMasterSecret": "YOUR_API_KEY_MASTER_SECRET_32_PLUS_CHARS",
2727
"auth": {
2828
"jwtSecret": "YOUR_JWT_SECRET_64_PLUS_CHARS",
29-
"jwtExpiryHours": 24
29+
"jwtExpiryHours": 24,
30+
"githubClientId": "",
31+
"githubClientSecret": ""
3032
},
3133
"mail": {
3234
"backend": "smtp",

cloud/deploy/setup.sh

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,35 @@ else
475475
fi
476476
API_KEY_SECRET=${INPUT_API_KEY_SECRET:-$DEFAULT_API_KEY_SECRET}
477477

478+
# ============================================================================
479+
# GitHub OAuth Configuration (optional)
480+
# ============================================================================
481+
echo ""
482+
echo -e "${BLUE}GitHub OAuth (optional - for GitHub login & sync):${NC}"
483+
print_info "Create OAuth App at https://github.com/settings/developers"
484+
print_info "Callback URL: \${baseUrl}/api/auth/github/callback"
485+
echo ""
486+
487+
CURRENT_GITHUB_CLIENT_ID=$(config_get '.auth.githubClientId' '')
488+
CURRENT_GITHUB_CLIENT_SECRET=$(config_get '.auth.githubClientSecret' '')
489+
490+
read -p "GitHub OAuth Client ID [$CURRENT_GITHUB_CLIENT_ID]: " GITHUB_CLIENT_ID
491+
GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID:-$CURRENT_GITHUB_CLIENT_ID}
492+
493+
if [ -n "$GITHUB_CLIENT_ID" ]; then
494+
if [ -n "$CURRENT_GITHUB_CLIENT_SECRET" ]; then
495+
print_info "GitHub Client Secret exists (hidden)"
496+
read -s -p "GitHub Client Secret [keep existing]: " INPUT_GITHUB_SECRET
497+
echo ""
498+
GITHUB_CLIENT_SECRET=${INPUT_GITHUB_SECRET:-$CURRENT_GITHUB_CLIENT_SECRET}
499+
else
500+
read -s -p "GitHub Client Secret: " GITHUB_CLIENT_SECRET
501+
echo ""
502+
fi
503+
else
504+
GITHUB_CLIENT_SECRET=""
505+
fi
506+
478507
# Preserve other existing config values
479508
CURRENT_JWT_EXPIRY=$(config_get '.auth.jwtExpiryHours' '24')
480509
CURRENT_REG=$(config_get '.features.registration' 'true')
@@ -556,7 +585,9 @@ NEW_CONFIG=$(cat <<EOF
556585
"apiKeyMasterSecret": "${API_KEY_SECRET}",
557586
"auth": {
558587
"jwtSecret": "${JWT_SECRET}",
559-
"jwtExpiryHours": ${CURRENT_JWT_EXPIRY}
588+
"jwtExpiryHours": ${CURRENT_JWT_EXPIRY},
589+
"githubClientId": "${GITHUB_CLIENT_ID}",
590+
"githubClientSecret": "${GITHUB_CLIENT_SECRET}"
560591
},
561592
"mail": {
562593
"backend": "${MAIL_BACKEND}",

0 commit comments

Comments
 (0)