|
| 1 | +// |
| 2 | +// IssueReport.swift |
| 3 | +// |
| 4 | +// CotEditor |
| 5 | +// https://coteditor.com |
| 6 | +// |
| 7 | +// Created by 1024jp on 2024-02-13. |
| 8 | +// |
| 9 | +// --------------------------------------------------------------------------- |
| 10 | +// |
| 11 | +// © 2024 1024jp |
| 12 | +// |
| 13 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 14 | +// you may not use this file except in compliance with the License. |
| 15 | +// You may obtain a copy of the License at |
| 16 | +// |
| 17 | +// https://www.apache.org/licenses/LICENSE-2.0 |
| 18 | +// |
| 19 | +// Unless required by applicable law or agreed to in writing, software |
| 20 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 21 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 22 | +// See the License for the specific language governing permissions and |
| 23 | +// limitations under the License. |
| 24 | +// |
| 25 | + |
| 26 | +import Foundation |
| 27 | + |
| 28 | +struct IssueReport { |
| 29 | + |
| 30 | + var locale: Locale = .current |
| 31 | + |
| 32 | + |
| 33 | + /// The generic report title. |
| 34 | + var title: String { |
| 35 | + |
| 36 | + String(localized: "IssueReport.title", defaultValue: "Issue Report", table: "IssueReport", locale: self.locale, comment: "document title") |
| 37 | + } |
| 38 | + |
| 39 | + |
| 40 | + /// Report template with user environment info. |
| 41 | + var template: String { |
| 42 | + |
| 43 | + [[self.description, |
| 44 | + String(repeating: "-", count: 25), |
| 45 | + Heading.environment.display(for: self.locale), |
| 46 | + self.environment, |
| 47 | + ].joined(separator: String(repeating: "\n", count: 2)), |
| 48 | + |
| 49 | + Heading.allCases[1...] |
| 50 | + .map { $0.display(for: self.locale) } |
| 51 | + .joined(separator: String(repeating: "\n", count: 3)) |
| 52 | + ].joined(separator: String(repeating: "\n", count: 3)) |
| 53 | + } |
| 54 | + |
| 55 | + |
| 56 | + // MARK: Private Methods |
| 57 | + |
| 58 | + private static var issueLink = "[GitHub Issues](https://github.com/coteditor/CotEditor/issues)" |
| 59 | + private static var mail = "<coteditor.github@gmail.com>" |
| 60 | + |
| 61 | + |
| 62 | + private var description: String { |
| 63 | + |
| 64 | + String(localized: "IssueReport.description", |
| 65 | + defaultValue: "Fill the following template, and post it on \(Self.issueLink) or send to \(Self.mail) Please note that the contents of the sent email can be shared on the Issue page. Please write the contents either in English or in Japanese.", |
| 66 | + table: "IssueReport", |
| 67 | + comment: "%1$@ is a link to a web page and %2$@ is an e-mail") |
| 68 | + } |
| 69 | + |
| 70 | + |
| 71 | + private var environment: String { |
| 72 | + |
| 73 | + """ |
| 74 | + - CotEditor: \(Bundle.main.shortVersion) (\(Bundle.main.bundleVersion)) |
| 75 | + - System: macOS \(ProcessInfo.processInfo.operatingSystemVersionString) |
| 76 | + - Language: \(self.appLanguage ?? "–") |
| 77 | + """ |
| 78 | + } |
| 79 | + |
| 80 | + |
| 81 | + /// The current app localization in English. |
| 82 | + private var appLanguage: String? { |
| 83 | + |
| 84 | + self.locale.language.languageCode.flatMap { Locale.en.localizedString(forLanguageCode: $0.identifier) } |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | + |
| 89 | +private extension IssueReport { |
| 90 | + |
| 91 | + enum Heading: CaseIterable { |
| 92 | + |
| 93 | + case environment |
| 94 | + case shortDescription |
| 95 | + case stepsToReproduce |
| 96 | + case expectedResult |
| 97 | + |
| 98 | + |
| 99 | + func display(for locale: Locale) -> String { |
| 100 | + |
| 101 | + (locale == .en) ? "## \(self.label(locale: locale))" : "## \(self.label(locale: .en)) (\(self.label(locale: locale)))" |
| 102 | + } |
| 103 | + |
| 104 | + |
| 105 | + private func label(locale: Locale) -> String { |
| 106 | + |
| 107 | + switch self { |
| 108 | + case .environment: |
| 109 | + String(localized: "IssueReport.Heading.environment", |
| 110 | + defaultValue: "Environment", |
| 111 | + table: "IssueReport", locale: locale) |
| 112 | + case .shortDescription: |
| 113 | + String(localized: "IssueReport.Heading.shortDescription", |
| 114 | + defaultValue: "Short Description", |
| 115 | + table: "IssueReport", locale: locale) |
| 116 | + case .stepsToReproduce: |
| 117 | + String(localized: "IssueReport.Heading.stepsToReproduce", |
| 118 | + defaultValue: "Steps to Reproduce the Issue", |
| 119 | + table: "IssueReport", locale: locale) |
| 120 | + case .expectedResult: |
| 121 | + String(localized: "IssueReport.Heading.expectedResult", |
| 122 | + defaultValue: "Expected Result", |
| 123 | + table: "IssueReport", locale: locale) |
| 124 | + } |
| 125 | + } |
| 126 | + } |
| 127 | +} |
| 128 | + |
| 129 | + |
| 130 | +private extension Locale { |
| 131 | + |
| 132 | + static let en = Locale(identifier: "en") |
| 133 | +} |
0 commit comments