Fix key copying animation

This commit is contained in:
Shadowfacts 2022-09-16 22:00:52 -04:00
parent 13d4ce0ab7
commit 94c39fb5c5
1 changed files with 49 additions and 26 deletions

View File

@ -12,6 +12,7 @@ struct KeyView: View {
let key: TOTPKey
let currentCode: TOTPCode
@State private var copying = false
@State private var copiedLabelWidth: CGFloat = 0
private var formattedCode: String {
let code = currentCode.code
@ -27,36 +28,48 @@ struct KeyView: View {
var body: some View {
Button(action: self.copy) {
HStack {
VStack(alignment: .leading) {
Text(key.issuer)
.font(.title3)
if let label = key.label, !label.isEmpty {
Text(label)
.font(.footnote)
ZStack {
HStack {
VStack(alignment: .leading) {
Text(key.issuer)
.font(.title3)
if let label = key.label, !label.isEmpty {
Text(label)
.font(.footnote)
}
}
Spacer()
}
HStack {
Spacer()
Text(formattedCode)
.font(.system(.title2, design: .monospaced))
.opacity(copying ? 0 : 1)
Text("Copied!")
.font(.title2)
.opacity(copying ? 1 : 0)
// this nonsense shouldn't be necessary, but the transition only works the first time a code is copied, for some indiscernible reason
.background(GeometryReader { proxy in
Color.clear
.preference(key: CopiedLabelWidth.self, value: proxy.size.width)
.onPreferenceChange(CopiedLabelWidth.self) { newValue in
copiedLabelWidth = newValue
}
})
}
.offset(x: copying ? 0 : copiedLabelWidth)
.clipped()
}
Spacer()
if copying {
Text("Copied!")
.font(.title2)
.transition(.move(edge: .trailing).combined(with: .opacity))
} else {
Text(formattedCode)
.font(.system(.title2, design: .monospaced))
.transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)).combined(with: .opacity))
}
// Text("\(currentCode.validUntil, style: .relative)")
// .font(.body.monospacedDigit())
.padding(.trailing, 8)
// I don't think this TimelineView should be necessary since the CodeHolder timer fires every .5 seconds
TimelineView(.animation) { (ctx) in
ZStack {
CircularProgressView(progress: progress(at: Date()), colorChangeThreshold: 5.0 / Double(key.period))
CircularProgressView(progress: progress(at: ctx.date), colorChangeThreshold: 5.0 / Double(key.period))
Text(Int(round(currentCode.validUntil.timeIntervalSinceNow)).description)
.font(.caption.monospacedDigit())
@ -79,12 +92,22 @@ struct KeyView: View {
withAnimation(.easeInOut(duration: 0.5)) {
copying = true
}
withAnimation(.easeInOut(duration: 0.5).delay(0.65)) {
copying = false
// .easeInOut(duration: 0.5).delay(0.65) does not work any more
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(650)) {
withAnimation(.easeInOut(duration: 0.5)) {
copying = false
}
}
}
}
private struct CopiedLabelWidth: PreferenceKey {
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
struct KeyView_Previews: PreviewProvider {
static var key: TOTPKey {
TOTPKey(urlComponents: URLComponents(string: "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example")!)!