Native app facelift, extension UI tweaks, bug fixes.

Show/Hide Button for private key in Options page.

Move experimental page into separate sub-folder.

Move delegation wizard to sub-folder.

Move permission page into separate folder.

Basic functional SwiftUI look for the app.

Beginning to define the main app view.

NavigationStack and Privacy Policy

Show App Icon on main screen.

Getting Started: macOS

Getting Started: iPhone

Getting Started: iPad

Removing old default UIKit code.

Added "No Thanks" toggle to the relay reminder.

Clearly indicate in the Settings page when a profile is a delegated profile.

Changed recommended relays to all public relays.

Use x-cloak in all the places.

Fix bundle display name to use capital N.

Added copy button to pubkey in settings.

Window default size.

Updating event kind list.

Allow events to be copied by clicking on them in the event log.

Tweaking the colors for a more purple-ish look.

Added Tips and Tricks view to native app.

Move utilities modules into separate folder.

Rename event_log files to event_history to escape some content blockers.

Renamed Event Log to Event History in the UI as well.
This commit is contained in:
Ryan Breen
2023-02-16 21:48:47 -05:00
parent 75274aed27
commit 8322aca674
56 changed files with 849 additions and 481 deletions

View File

@@ -1,6 +1,15 @@
{
"colors" : [
{
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.665",
"green" : "0.271",
"red" : "0.509"
}
},
"idiom" : "universal"
}
],

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "Icon-512.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "ipad-menu.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "ipad-popup.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "ipad-url-bar.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "iphone-menu.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 KiB

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "iphone-popup.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "iphone-url-bar.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "default-popup.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "toolbar-inactive.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,62 @@
//
// GettingStartediPad.swift
// Nostore
//
// Created by Ryan Breen on 2/18/23.
//
import SwiftUI
struct GettingStartediPad: View {
var body: some View {
ScrollView {
Text("Getting Started")
.font(.largeTitle)
.foregroundColor(.accentColor)
Text("iPad")
.font(.title)
.foregroundColor(.accentColor)
Text("")
Text("""
Upon installation of the app, go to **Settings -> Safari -> Extensions** and enable **Nostore**. Open Safari and look in the toolbar, where you will see the \(Image(systemName: "puzzlepiece.extension")) icon:
""")
.padding([.horizontal, .top], 20)
Image("ipad-url-bar")
.resizable()
.scaledToFit()
.frame(maxWidth: 512)
.border(Color.accentColor, width: 2)
.padding([.top])
Text("You will be greeted by a menu like below:").padding([.top], 20)
Image("ipad-menu")
.resizable()
.scaledToFit()
.frame(maxWidth: 512)
.border(Color.accentColor, width: 2)
.padding([.top])
Text("""
The **Nostore** logo is gray, indicating the extension is inactive for this site, and must be activated first. Click on the button, and give Nostore permission to access the current site. Now the Nostore logo will appear in color, and you can click it again to access the extension.
""").multilineTextAlignment(.leading)
.padding([.horizontal, .top], 20)
Image("ipad-popup")
.resizable()
.scaledToFit()
.frame(maxWidth: 512)
.border(Color.accentColor, width: 2)
.padding([.top])
Text("You have a default profile (with a random key) setup to start. Click the **Settings** button to configure your own keys, if you have them.").padding([.top, .bottom], 20)
}
}
}
struct GettingStartediPad_Previews: PreviewProvider {
static var previews: some View {
GettingStartediPad()
}
}

View File

@@ -0,0 +1,56 @@
//
// GettingStartedmacOS.swift
// Nostore
//
// Created by Ryan Breen on 2/18/23.
//
import SwiftUI
struct GettingStartedmacOS: View {
var body: some View {
ScrollView {
Text("Getting Started")
.font(.largeTitle)
.foregroundColor(.accentColor)
Text("macOS")
.font(.title)
.foregroundColor(.accentColor)
Text("")
Text("Upon installation of the app, open Safari. Click on the **Safari menu -> Settings... -> Extensions tab** and activate the **Nostore** extension. You will now see the Nostore icon in your Safari toolbar. For example:")
.padding([.horizontal, .top], 20)
Image("macos-toolbar-inactive")
.resizable()
.scaledToFit()
.frame(maxWidth: 512)
.border(Color.accentColor, width: 2)
.padding([.top])
Text("""
On the right, you can see the Nostore logo, and it is gray (or **inactive**). This means that it does not have permission to access the current website.
The first time you visit a Nostr client, you will need to click the icon to give Nostore permission to access the site.
Once active, the icon will become colored and you can select it again, where you will be greeted with a similar popup:
""").multilineTextAlignment(.leading)
.padding([.horizontal, .top], 20)
Image("macos-default-popup")
.resizable()
.scaledToFit()
.frame(maxWidth: 512)
.border(Color.accentColor, width: 2)
.padding([.top])
Text("You have a default profile (with a random key) setup to start. Click the **Settings** button to configure your own keys, if you have them.").padding([.top, .bottom], 20)
}
}
}
struct GettingStartedmacOS_Previews: PreviewProvider {
static var previews: some View {
GettingStartedmacOS()
}
}

View File

@@ -0,0 +1,60 @@
//
// GettingStartediPhone.swift
// Nostore
//
// Created by Ryan Breen on 2/18/23.
//
import SwiftUI
struct GettingStartediPhone: View {
var body: some View {
ScrollView {
Text("Getting Started")
.font(.largeTitle)
.foregroundColor(.accentColor)
Text("iPhone")
.font(.title)
.foregroundColor(.accentColor)
Spacer(minLength: 20.0)
Text("Upon installation of the app, goto **Settings -> Safari -> Extension** and enable the **Nostore** extension. Then open Safari and look in the toolbar, where you will see the \(Image(systemName: "textformat.size")) icon:")
.padding([.horizontal, .top], 20)
Image("iphone-url-bar")
.resizable()
.scaledToFit()
.frame(maxWidth: 512)
.border(Color.accentColor, width: 2)
.padding([.top])
Text("You will be greeted by a menu like below:").padding([.top], 20)
Image("iphone-menu")
.resizable()
.scaledToFit()
.frame(maxWidth: 512)
.border(Color.accentColor, width: 2)
.padding([.top])
Text("""
The **Nostore** logo is gray, indicating the extension is inactive for this site, and must be activated first. Click on the button, and give Nostore permission to access the current site. Now the Nostore logo will appear in color, and you can click it again to access the extension.
""").multilineTextAlignment(.leading)
.padding([.horizontal, .top], 20)
Image("iphone-popup")
.resizable()
.scaledToFit()
.frame(maxWidth: 512)
.border(Color.accentColor, width: 2)
.padding([.top])
Text("You have a default profile (with a random key) setup to start. Click the **Settings** button to configure your own keys, if you have them.").padding([.top, .bottom], 20)
}
}
}
struct GettingStartediPhone_Previews: PreviewProvider {
static var previews: some View {
GettingStartediPhone()
}
}

View File

@@ -0,0 +1,65 @@
//
// HelloView.swift
// Nostore
//
// Created by Ryan Breen on 2/17/23.
//
import SwiftUI
struct MainView: View {
var body: some View {
VStack {
NavigationStack {
Image("bigicon").resizable().frame(width: 150.0, height: 150.0)
Text("Nostore").font(.title)
Text("A Safari Nostr Extension").font(.title2)
NavigationLink("Privacy Policy") {
PrivacyPolicyView()
}
#if macOS
.buttonStyle(.link)
#endif
.padding(.all, 3.0)
NavigationLink("Getting Started: iPhone") {
GettingStartediPhone()
}
#if macOS
.buttonStyle(.link)
#endif
.padding(.all, 3.0)
NavigationLink("Getting Started: iPad") {
GettingStartediPad()
}
#if macOS
.buttonStyle(.link)
#endif
.padding(.all, 3.0)
NavigationLink("Getting Started: MacOS") {
GettingStartedmacOS()
}
#if macOS
.buttonStyle(.link)
#endif
.padding(.all, 3.0)
NavigationLink("Tips and Tricks") {
TipsAndTricks()
}
#if macOS
.buttonStyle(.link)
#endif
.padding(.all, 3.0)
}
}
}
}
struct MainView_Previews: PreviewProvider {
static var previews: some View {
MainView()
}
}

View File

@@ -0,0 +1,20 @@
//
// File.swift
// Nostore
//
// Created by Ryan Breen on 2/17/23.
//
import SwiftUI
@main
struct NostoreApp: App {
var body: some Scene {
WindowGroup("Nostore") {
MainView()
}
#if macOS
.defaultSize(width: 400, height: 500)
#endif
}
}

View File

@@ -0,0 +1,32 @@
//
// SwiftUIView.swift
// Nostore
//
// Created by Ryan Breen on 2/17/23.
//
import SwiftUI
struct PrivacyPolicyView: View {
var body: some View {
ScrollView {
Text("Privacy Policy")
.font(.largeTitle)
.foregroundColor(.accentColor)
Spacer(minLength: 20)
Text("""
**Nostore** is developed in the spirit of Nostr.
You, the user, own your data. The developers of this app collect no data, anonymous or otherwise.
This code of this application is fully auditable and available on our [GitHub page](https://github.com/ursuscamp/nostore).
""").multilineTextAlignment(.leading)
}.padding(.all)
}
}
struct PrivacyPolicyView_Previews: PreviewProvider {
static var previews: some View {
PrivacyPolicyView()
}
}

View File

@@ -0,0 +1,41 @@
//
// SwiftUIView.swift
// Nostore
//
// Created by Ryan Breen on 2/19/23.
//
import SwiftUI
struct TipsAndTricks: View {
var body: some View {
ScrollView {
Text("Tips and Tricks")
.font(.largeTitle)
.foregroundColor(.accentColor)
Spacer(minLength: 20.0)
Text("Try a few of these:")
.frame(maxWidth: .infinity, alignment: .leading)
Spacer(minLength: 20)
Text("""
1. You can have multiple profiles, each corresponding to a different key.
2. Click **Event History** in settings to see a list of all events signed by the extension.
3. Each client has its own set of permissions. You can review them at any time in **Settings**. They are organized by application host.
4. Clicking the event text in the **Event History** will copy a the raw event JSON.
5. If you have authorized the extension to talk to the client, but still don't see a special extension login button on the site, try hitting refresh on the site. The client may not recognize the extension code until you do that.
""")
.frame(maxWidth: .infinity, alignment: .leading)
.padding([.horizontal], 25)
}.padding(.all)
}
}
struct Tipsandtricks_Previews: PreviewProvider {
static var previews: some View {
TipsAndTricks()
}
}