Skip to content

Commit

Permalink
Adds section to UserInfo view to edit basic list of session personas
Browse files Browse the repository at this point in the history
  • Loading branch information
atreat committed Jul 25, 2024
1 parent 05992c0 commit 4113529
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 6 deletions.
8 changes: 8 additions & 0 deletions Examples/BrandGame/BrandGame.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
7B3143C62AFF1E7D00BA0D2F /* ReflexGameModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3143C52AFF1E7D00BA0D2F /* ReflexGameModel.swift */; };
7B3229DC2B2950D500664F04 /* BubbleMinigameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B56309F2ABF323400E0DF39 /* BubbleMinigameView.swift */; };
7B3BD2192BBC5A1600938444 /* StdoutExporter in Frameworks */ = {isa = PBXBuildFile; productRef = 7B3BD2182BBC5A1600938444 /* StdoutExporter */; };
7B3CBA0A2C52E67600688E7B /* PersonaGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3CBA092C52E67600688E7B /* PersonaGrid.swift */; };
7B4C0BDF2BA9F93400F0BC37 /* App+SmokeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C0BDE2BA9F93400F0BC37 /* App+SmokeTest.swift */; };
7B4FFC2D2B1E5B7B006239F7 /* Endpoints+InfoPlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4FFC2C2B1E5B7B006239F7 /* Endpoints+InfoPlist.swift */; };
7B4FFC332B1E811B006239F7 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4FFC322B1E811B006239F7 /* UserInfo.swift */; };
Expand All @@ -33,6 +34,7 @@
7B62ADA32B0068280087C2AE /* SimonMinigameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B62ADA22B0068280087C2AE /* SimonMinigameView.swift */; };
7B62ADA52B0068960087C2AE /* SimonGameModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B62ADA42B0068960087C2AE /* SimonGameModel.swift */; };
7B7341E12BD4AD100026D8B8 /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7341E02BD4AD100026D8B8 /* LazyView.swift */; };
7B8BE3F92C5154BC006B0BF3 /* PillText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BE3F82C5154BC006B0BF3 /* PillText.swift */; };
7BBBCD582BD0205C00BC289A /* StdoutLogExporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBBCD572BD0205C00BC289A /* StdoutLogExporter.swift */; };
7BBBCD5B2BD07CE000BC289A /* GitInfo+InfoPlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBBCD5A2BD07CE000BC289A /* GitInfo+InfoPlist.swift */; };
7BBBCD5D2BD07DE600BC289A /* App+GitInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBBCD5C2BD07DE600BC289A /* App+GitInfo.swift */; };
Expand Down Expand Up @@ -89,6 +91,7 @@
7B3143B82AFDC8EC00BA0D2F /* RightBracketShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RightBracketShape.swift; sourceTree = "<group>"; };
7B3143BE2AFDECCE00BA0D2F /* Icon+Meta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Icon+Meta.swift"; sourceTree = "<group>"; };
7B3143C52AFF1E7D00BA0D2F /* ReflexGameModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReflexGameModel.swift; sourceTree = "<group>"; };
7B3CBA092C52E67600688E7B /* PersonaGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonaGrid.swift; sourceTree = "<group>"; };
7B4C0BDE2BA9F93400F0BC37 /* App+SmokeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "App+SmokeTest.swift"; sourceTree = "<group>"; };
7B4FFC2C2B1E5B7B006239F7 /* Endpoints+InfoPlist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Endpoints+InfoPlist.swift"; sourceTree = "<group>"; };
7B4FFC2E2B1E5D0F006239F7 /* embrace.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = embrace.xcconfig; sourceTree = "<group>"; };
Expand All @@ -111,6 +114,7 @@
7B62ADA22B0068280087C2AE /* SimonMinigameView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimonMinigameView.swift; sourceTree = "<group>"; };
7B62ADA42B0068960087C2AE /* SimonGameModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimonGameModel.swift; sourceTree = "<group>"; };
7B7341E02BD4AD100026D8B8 /* LazyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyView.swift; sourceTree = "<group>"; };
7B8BE3F82C5154BC006B0BF3 /* PillText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillText.swift; sourceTree = "<group>"; };
7BBBCD4D2BCEC14000BC289A /* run.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = run.sh; sourceTree = "<group>"; };
7BBBCD4E2BCEC14000BC289A /* upload */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = upload; sourceTree = "<group>"; };
7BBBCD572BD0205C00BC289A /* StdoutLogExporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StdoutLogExporter.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -213,6 +217,8 @@
isa = PBXGroup;
children = (
7B4FFC322B1E811B006239F7 /* UserInfo.swift */,
7B8BE3F82C5154BC006B0BF3 /* PillText.swift */,
7B3CBA092C52E67600688E7B /* PersonaGrid.swift */,
);
path = UserInfo;
sourceTree = "<group>";
Expand Down Expand Up @@ -622,6 +628,7 @@
7B62AD9F2B00608A0087C2AE /* AppSettings+Environment.swift in Sources */,
7B5630902ABE743400E0DF39 /* ContentView.swift in Sources */,
FA4C5F332C486E13005C0371 /* CreateSpanView.swift in Sources */,
7B8BE3F92C5154BC006B0BF3 /* PillText.swift in Sources */,
7B3143C62AFF1E7D00BA0D2F /* ReflexGameModel.swift in Sources */,
FAFDA3D72C34273100AD17CF /* MemoryPressureSimulatorView.swift in Sources */,
7B5630A52AC1331000E0DF39 /* Color+Random.swift in Sources */,
Expand All @@ -632,6 +639,7 @@
FAFDA3D42C333FC900AD17CF /* Request.swift in Sources */,
7B4C0BDF2BA9F93400F0BC37 /* App+SmokeTest.swift in Sources */,
7B3143B72AFDC52D00BA0D2F /* RightDotShape.swift in Sources */,
7B3CBA0A2C52E67600688E7B /* PersonaGrid.swift in Sources */,
FA9505162B86640F00562A4C /* LoggingView.swift in Sources */,
7B3143B92AFDC8EC00BA0D2F /* RightBracketShape.swift in Sources */,
7B3143B52AFDC50E00BA0D2F /* LeftDotShape.swift in Sources */,
Expand Down
71 changes: 71 additions & 0 deletions Examples/BrandGame/BrandGame/View/Menu/UserInfo/PersonaGrid.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// Copyright © 2023 Embrace Mobile, Inc. All rights reserved.
//

import SwiftUI
import EmbraceIO

struct PersonaGrid: View {

let lifespan: MetadataLifespan
@ObservedObject var user: UserInfo.EmbraceUser

var body: some View {
Grid(verticalSpacing: 6.0) {
ForEach(personaGridRows(), id: \.self) { row in
GridRow {
ForEach(row) { personaOption in
PillText(
personaOption.rawValue,
selected: user.hasPersona(personaOption),
style: colorForPersona(persona: personaOption)
).onTapGesture {
user.toggle(persona: personaOption, lifespan: lifespan)
}
}
}
}
}
}

func personaGridRows(size: Int = 3) -> [[PersonaTag]] {
let count = Self.quickPersonas.count

return stride(from: 0, to: count, by: size).map {
Array(Self.quickPersonas[$0 ..< Swift.min($0 + size, count)])
}
}

func colorForPersona(persona: PersonaTag) -> Color {
let idx = persona.rawValue.count % Self.personaColors.count
return Self.personaColors[idx]
}
}

extension PersonaGrid {
static var quickPersonas: [PersonaTag] {
[
PersonaTag.free,
PersonaTag.preview,
PersonaTag.subscriber,
PersonaTag.payer,
PersonaTag.guest,
PersonaTag.pro,
PersonaTag.mvp,
PersonaTag.vip
]
}

static var personaColors: [Color] {
[
Color.embraceLead,
Color.embracePink,
Color.embracePurple,
Color.embraceSilver
]
}
}

#Preview {
PersonaGrid(lifespan: .session, user: .init())
}
45 changes: 45 additions & 0 deletions Examples/BrandGame/BrandGame/View/Menu/UserInfo/PillText.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// Copyright © 2023 Embrace Mobile, Inc. All rights reserved.
//

import SwiftUI

struct PillText<S: ShapeStyle>: View {
let text: String
let selected: Bool
let cornerSize: CGSize
let style: S

init(
_ text: String,
selected: Bool = false,
style: S = Color.primary,
cornerSize: CGSize = .init(width: 24.0, height: 24.0)
) {

self.text = text
self.selected = selected
self.cornerSize = cornerSize
self.style = style
}

var body: some View {
Text(text)
.padding(.horizontal, cornerSize.width / 2)
.padding(.vertical, cornerSize.height / 4)
.background( style.opacity(selected ? 1 : 0))
.clipShape(RoundedRectangle(cornerSize: cornerSize))
.overlay(
RoundedRectangle(cornerSize: cornerSize)
.stroke(style, lineWidth: 2)
) // Border
}
}

#Preview("Unselected") {
PillText("Text", selected: false, style: Color.embracePink)
}

#Preview("Selected") {
PillText("Text", selected: true, style: Color.embracePink)
}
89 changes: 83 additions & 6 deletions Examples/BrandGame/BrandGame/View/Menu/UserInfo/UserInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,31 +50,59 @@ struct UserInfo: View {
email = metadata.userEmail ?? ""
}

func clear() {
func clearProperties() {
Embrace.client?.metadata.clearUserProperties()

// Need to clear local state as well
username.removeAll()
identifier.removeAll()
email.removeAll()
}

func clearPersonas() {
try? Embrace.client?.metadata.removeAllPersonas()
objectWillChange.send()
}

func toggle(persona: PersonaTag, lifespan: MetadataLifespan) {
if hasPersona(persona) {
try? Embrace.client?.metadata.remove(persona: persona, lifespan: lifespan)
} else {
try? Embrace.client?.metadata.add(persona: persona, lifespan: lifespan)
}

objectWillChange.send()
}

func hasPersona(_ persona: PersonaTag) -> Bool {
let currentPersonas = Embrace.client?.metadata.currentPersonas ?? []

return currentPersonas.contains(persona)
}
}

@Environment(\.dismiss) private var dismiss
// Retrieve scenePhase so we can see session metadata removed when app is foregrounded.
@Environment(\.scenePhase) var scenePhase

@ObservedObject var user = EmbraceUser()
@StateObject var user = EmbraceUser()

var body: some View {
Form {
Section {
Section(header: Text("Properties")) {
TextField("Username", text: $user.username)
TextField("Identifier", text: $user.identifier)
TextField("Email", text: $user.email)

Button("Clear All") {
user.clearProperties()
}
}

Section {
Section(header: Text("Personas - Session")) {
PersonaGrid(lifespan: .session, user: user)

Button("Clear All") {
user.clear()
user.clearPersonas()
}
}
}
Expand All @@ -83,10 +111,59 @@ struct UserInfo: View {
.onAppear {
user.refresh()
user.listen()
}.onChange(of: scenePhase) { _, newPhase in
if newPhase == .active {
user.refresh()
}
}

}

func personaGridRows(size: Int = 3) -> [[PersonaTag]] {
let count = Self.quickPersonas.count

return stride(from: 0, to: count, by: size).map {
Array(Self.quickPersonas[$0 ..< Swift.min($0 + size, count)])
}
}

func colorForPersona(persona: PersonaTag) -> Color {
let idx = persona.rawValue.count % Self.personaColors.count
return Self.personaColors[idx]
}

}

extension UserInfo {
static var quickPersonas: [PersonaTag] {
[
PersonaTag.free,
PersonaTag.preview,
PersonaTag.subscriber,
PersonaTag.payer,
PersonaTag.guest,
PersonaTag.pro,
PersonaTag.mvp,
PersonaTag.vip
]
}

static var personaColors: [Color] {
[
Color.embraceLead,
Color.embracePink,
Color.embracePurple,
Color.embraceSilver
]
}
}

extension PersonaTag: Identifiable {
public var id: String { rawValue }
}

extension PersonaTag: Hashable { }

#Preview {
UserInfo()
}

0 comments on commit 4113529

Please sign in to comment.