Skip to content

Commit

Permalink
Merge pull request #231 from tatsuz0u/develop
Browse files Browse the repository at this point in the history
Refactoring
  • Loading branch information
tatsuz0u authored Feb 16, 2022
2 parents c2b2c84 + 2a69541 commit e4d4807
Show file tree
Hide file tree
Showing 21 changed files with 1,043 additions and 59 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
types: [closed]
env:
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app
APP_VERSION: '2.2.1'
APP_VERSION: '2.2.2'
SCHEME_NAME: 'EhPanda'
ALTSTORE_JSON_PATH: './AltStore.json'
BUILDS_PATH: '/tmp/action-builds'
Expand Down
90 changes: 49 additions & 41 deletions EhPanda.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Binary file removed EhPanda/App/Icons/AppIcon_Developer.png
Binary file not shown.
Binary file modified EhPanda/App/Icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added EhPanda/App/Icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added EhPanda/App/Icons/AppIcon_Developer_iPad.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified EhPanda/App/Icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed EhPanda/App/Icons/[email protected]
Binary file not shown.
Binary file modified EhPanda/App/Icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified EhPanda/App/Icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
Binary file modified EhPanda/App/Icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions EhPanda/Models/Support/LiveText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct LiveTextBounds: Equatable {
}

func expandingHalfHeight(_ size: CGSize) -> Self {
expanding(size, radius: getHeight(size) / 2)
expanding(size: size, width: 0, height: getHeight(size) / 2)
}
func getHeight(_ size: CGSize) -> Double {
let topLeft = topLeft * size
Expand All @@ -50,12 +50,12 @@ struct LiveTextBounds: Equatable {
}

// Returns a expanded version with a specific radius
private func expanding(_ size: CGSize, radius: Double) -> Self {
private func expanding(size: CGSize, width: Double, height: Double) -> Self {
let angle = 360 - getAngle(size)
let projectedBottom = hypotenuse(radius: radius, angle: angle)
let projectedRight = hypotenuse(radius: radius, angle: angle + 90)
let projectedTop = hypotenuse(radius: radius, angle: angle + 90 * 2)
let projectedLeft = hypotenuse(radius: radius, angle: angle + 90 * 3)
let projectedBottom = hypotenuse(longestSideLength: height, angle: angle)
let projectedRight = hypotenuse(longestSideLength: width, angle: angle + 90)
let projectedTop = hypotenuse(longestSideLength: height, angle: angle + 90 * 2)
let projectedLeft = hypotenuse(longestSideLength: width, angle: angle + 90 * 3)

let multipliedTopLeft = topLeft * size
let multipliedTopRight = topRight * size
Expand Down Expand Up @@ -83,9 +83,9 @@ struct LiveTextBounds: Equatable {
bottomLeft: bottomLeft / size, bottomRight: bottomRight / size
)
}
private func hypotenuse(radius: Double, angle: Double) -> CGPoint {
private func hypotenuse(longestSideLength: Double, angle: Double) -> CGPoint {
let radian = 2 * .pi / 360 * angle
return .init(x: sin(radian) * radius, y: cos(radian) * radius)
return .init(x: sin(radian) * longestSideLength, y: cos(radian) * longestSideLength)
}
}

Expand Down
10 changes: 5 additions & 5 deletions EhPanda/View/Detail/DataFlow/DetailStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -372,17 +372,17 @@ let detailReducer = Reducer<DetailState, DetailAction, DetailEnvironment>.recurs
return .none
}
}
.haptics(
unwrapping: \.route,
case: /DetailState.Route.postComment,
hapticClient: \.hapticClient
)
.haptics(
unwrapping: \.route,
case: /DetailState.Route.detailSearch,
hapticClient: \.hapticClient,
style: .soft
)
.haptics(
unwrapping: \.route,
case: /DetailState.Route.postComment,
hapticClient: \.hapticClient
)
.haptics(
unwrapping: \.route,
case: /DetailState.Route.torrents,
Expand Down
2 changes: 1 addition & 1 deletion EhPanda/View/Reading/Support/LiveTextHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ final class LiveTextHandler: ObservableObject {
let isAngleValid = angle < 5 || angle > (360 - 5)
let aHeight = item.bounds.getHeight(size)
let bHeight = newItem.bounds.getHeight(size)
let isHeightValid = abs(aHeight - bHeight) < (min(aHeight, bHeight))
let isHeightValid = abs(aHeight - bHeight) < (min(aHeight, bHeight) / 2)

guard isAngleValid && isHeightValid else { return false }
return self.polygonsIntersecting(
Expand Down
17 changes: 14 additions & 3 deletions EhPanda/View/Reading/Support/LiveTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,17 @@ struct LiveTextView: View {
}
}
.map { (id, block) in
let bounds = block.bounds.expandingHalfHeight(size)
let rect = CGRect(x: 0, y: 0, width: bounds.getWidth(size), height: bounds.getHeight(size))
let expandingSize = 4.0
let bounds = block.bounds
let topLeft = bounds.topLeft * size
let rect = CGRect(
x: 0, y: 0,
width: bounds.getWidth(size) + expandingSize * 2,
height: bounds.getHeight(size) + expandingSize * 2)

let path = Path(roundedRect: rect, cornerRadius: bounds.getHeight(size) / 5)
.applying(CGAffineTransform(rotationAngle: block.bounds.getRadian(size)))
.offsetBy(dx: bounds.topLeft.x * width, dy: bounds.topLeft.y * height)
.offsetBy(dx: topLeft.x - expandingSize, dy: topLeft.y - expandingSize)
return (id, path)
}
context.withCGContext { cgContext in
Expand Down Expand Up @@ -165,3 +171,8 @@ private struct HighlightView: UIViewRepresentable {
uiView.text = text
}
}

// MARK: Definition
private func * (lhs: CGPoint, rhs: CGSize) -> CGPoint {
.init(x: lhs.x * rhs.width, y: lhs.y * rhs.height)
}
267 changes: 267 additions & 0 deletions EhPanda/View/Search/TagTip.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
//
// TagTip.swift
// EhPanda
//
// Created by xioxin on 2022/2/15.
//

import SwiftUI

let shortNsDic: [String: String] = [
"reclass": "r",
"language": "l",
"parody": "p",
"character": "c",
"group": "g",
"artist": "a",
"cosplayer": "cos",
"male": "m",
"female": "f",
"mixed": "x",
"other": "o",
"temp": ""
]

let namespaceScore: [String: Double] = [
"other": 10,
"female": 9,
"male": 8.5,
"mixed": 8,
"language": 2,
"artist": 2.5,
"cosplayer": 2.4,
"group": 2.2,
"parody": 3.3,
"character": 2.8,
"reclass": 1,
"temp": 0.1
]

struct TagItem: Identifiable {
var id: UUID = UUID()
var namespace: String
var key: String
var name: String

var shortNamespace: String {
shortNsDic[namespace] ?? namespace
}

var searchTerm: String {
let namespace = shortNamespace.isEmpty ? "" : "\(shortNamespace):"
let keyword = key.contains(" ") ? "\"\(key)$\"" : "\(key)$"
return namespace + keyword
}

func markTag(search: String) {}

func getMatchScore(keyword: String) -> TagSuggestion {
let namespaceScore = namespaceScore[namespace] ?? 0.0
var score: Double = 0.0
let key = key.lowercased()
let keyRange = key.range(of: keyword)
if let range = keyRange {
score += namespaceScore
* Double(search.count + 1)
/ Double(key.count)
* (range.contains(key.startIndex) ? 2.0 : 1.0)
}

let name = name.lowercased()
let nameRange = name.range(of: keyword)
if let range = nameRange {
score += namespaceScore
* Double(search.count + 1)
/ Double(name.count)
* (range.contains(name.startIndex) ? 2.0 : 1.0)
}
return TagSuggestion(tag: self, score: score, keyRange: keyRange, nameRange: nameRange)
}
}

struct TagSuggestion: Identifiable {
var id: UUID = UUID()
var tag: TagItem
var score: Double
var keyRange: Range<String.Index>?
var nameRange: Range<String.Index>?

var keyMatchLeft: String {
leftSideString(of: keyRange, string: tag.key)
}

var keyMatchFocal: String {
middleString(of: keyRange, string: tag.key)
}

var keyMatchRight: String {
rightSideString(of: keyRange, string: tag.key)
}

var nameMatchLeft: String {
leftSideString(of: nameRange, string: tag.name)
}

var nameMatchFocal: String {
middleString(of: nameRange, string: tag.name)
}

var nameMatchRight: String {
rightSideString(of: nameRange, string: tag.name)
}

func leftSideString(of range: Range<String.Index>?, string: String) -> String {
guard let range = range else { return string }
return .init(string[string.startIndex..<range.lowerBound])
}

func middleString(of range: Range<String.Index>?, string: String) -> String {
guard let range = range else { return "" }
return .init(string[range])
}

func rightSideString(of range: Range<String.Index>?, string: String) -> String {
guard let range = range else { return "" }
return .init(string[range.upperBound..<string.endIndex])
}
}

extension Array where Element == TagItem {
func getSuggests(_ term: String) -> [TagSuggestion] {
let term = term.lowercased()
var sTerm = term
var onlyNs: String?
if let col = term.firstIndex(of: ":") {
// Requires at least one character before the colon
if col >= term.index(term.startIndex, offsetBy: 1) {
let namespace = String(term[term.startIndex ..< col])
if let index = shortNsDic.index(forKey: namespace) {
onlyNs = shortNsDic[index].key
}
if let index = shortNsDic.firstIndex(where: {
$0 == namespace || $1 == namespace
}) {
onlyNs = shortNsDic[index].key
sTerm = String(term[term.index(col, offsetBy: 1) ..< term.endIndex])
}
}
}

var tagList = self
if onlyNs != nil {
tagList = tagList.filter { $0.namespace == onlyNs}
}

let suggestions = tagList
.compactMap { $0.getMatchScore(keyword: sTerm) }
.filter{$0.score > 0}
.sorted { $1.score > $0.score }

print(suggestions)
return suggestions
}
}

let allTagList: [TagItem] = [
TagItem(namespace: "language", key: "chinese", name: "中文"),
TagItem(namespace: "language", key: "english", name: "英语"),
TagItem(namespace: "female", key: "loli", name: "萝莉")
]

func pregReplace(_ text: String, pattern: String, with: String, options: NSRegularExpression.Options = []) -> String? {
let regex = try? NSRegularExpression(pattern: pattern, options: options)
return regex?.stringByReplacingMatches(
in: text, options: [], range: .init(location: 0, length: text.count), withTemplate: with
)
}

struct TagTip: View {
@State var input = ""
@State var suggests: [TagSuggestion] = []
@State var term: String = ""

func search(_ value: String) {
guard let value = pregReplace(value, pattern: " +", with: " ") else { return }
input = value
guard let regex = try? NSRegularExpression(pattern: "(\\S+:\".+?\"|\".+?\"|\\S+:\\S+|\\S+)") else { return }
let matchs = regex.matches(in: value, options: [], range: .init(location: 0, length: value.count))
let values: [String] = matchs.compactMap {
String(value[Range($0.range, in: value)!])
}
print(values)
if let last = values.last {
term = last
suggests = allTagList.getSuggests(last)
} else {
suggests = []
term = ""
}
}

var body: some View {
VStack {
HStack {
TextField("", text: $input)
.textFieldStyle(.roundedBorder)
.padding()
.onChange(of: input) { newValue in
search(newValue)
// autocomplete.autocomplete(input)
}
.toolbar {
ToolbarItem(placement: .keyboard) {
HStack {
Button("-/+") {}
.buttonStyle(.bordered)
Spacer()
Button("Finish") {}
.buttonStyle(.bordered)
}
.padding(.horizontal, 30)
}
}
.onSubmit{
print(input)
}
Button("Search"){
print(input)
}
.keyboardShortcut(.defaultAction)
}
List(suggests) { suggestion in
HStack {
VStack {
HStack(spacing: 0.0) {
Text(suggestion.nameMatchLeft).font(.body)
Text(suggestion.nameMatchFocal).background(Color.red).font(.body)
Text(suggestion.nameMatchRight).font(.body)
}
Spacer()
HStack(spacing: 0.0) {
Text(suggestion.tag.namespace).font(.caption)
Text(":")
Text(suggestion.keyMatchLeft).font(.caption)
Text(suggestion.keyMatchFocal).background(Color.red).font(.caption)
Text(suggestion.keyMatchRight).font(.caption)
}
}
.onTapGesture {
input = String(
input[input.startIndex..<input.index(input.endIndex, offsetBy: 0 - term.count)]
)
+ suggestion.tag.searchTerm + " "
}
Spacer()
Text("Exclude")
.onTapGesture {
input = String(
input[input.startIndex..<input.index(input.endIndex, offsetBy: 0 - term.count)]
)
+ "-" + suggestion.tag.searchTerm + " "
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
}
}
}
}
1 change: 1 addition & 0 deletions EhPandaTests/Models/HTMLFilename.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ enum HTMLFilename: String {

// Other
case ipBanned = "IPBanned"
case ehSetting = "EhSetting"
case galleryDetailWithGreeting = "GalleryDetailWithGreeting"
}
Loading

0 comments on commit e4d4807

Please sign in to comment.