Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/inamiy/sherlockforms
🕵️♂️ An elegant SwiftUI Form builder to create a searchable Settings and DebugMenu screens for iOS.
https://github.com/inamiy/sherlockforms
debug-menu hud swiftui swiftui-form toast
Last synced: 2 months ago
JSON representation
🕵️♂️ An elegant SwiftUI Form builder to create a searchable Settings and DebugMenu screens for iOS.
- Host: GitHub
- URL: https://github.com/inamiy/sherlockforms
- Owner: inamiy
- License: mit
- Created: 2022-02-14T12:50:37.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2023-03-24T15:43:22.000Z (almost 2 years ago)
- Last Synced: 2024-10-31T19:42:34.665Z (3 months ago)
- Topics: debug-menu, hud, swiftui, swiftui-form, toast
- Language: Swift
- Homepage:
- Size: 98.6 KB
- Stars: 124
- Watchers: 3
- Forks: 11
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# 🕵️♂️ SherlockForms
> What one man can invent Settings UI, another can discover its field.
>
> -- Sherlock FormsAn elegant SwiftUI Form builder to create a searchable Settings and DebugMenu screens for iOS.
(Supports from iOS 14, except `.searchable` works from iOS 15)
## Overview
| Normal | Searching | Context Menu |
|---|---|---|
| | | || UserDefaults | App Info | Device Info |
|---|---|---|
| | | |This repository consists of 3 modules:
1. `SherlockForms`: SwiftUI Form builder to enhance cell findability using iOS 15 `.searchable`.
- [x] Various form cells to automagically interact with `.searchable`, including Text, Button, Toggle, Picker, NavigationLink, etc.
- [x] "Copy text" from context menu by long-press
2. `SherlockDebugForms`: Useful app/device info-views and helper methods, specifically for debugging purpose.
- [x] App Info view
- [x] Device Info view
- [x] UserDefaults Editor
- [ ] TODO: File Browser
- [ ] TODO: Console Logger
3. `SherlockHUD`: Standalone, simple-to-use Notification View (Toast) UI used in `SherlockForms`## Examples
### `SherlockForms` & `SherlockDebugForms`
From [SherlockForms-Gallery app](Examples/SherlockForms-Gallery.swiftpm):
```swift
import SwiftUI
import SherlockDebugForms/// NOTE: Each view that owns `SherlockForm` needs to conform to `SherlockView` protocol.
@MainActor
struct RootView: View, SherlockView
{
/// NOTE:
/// `searchText` is required for `SherlockView` protocol.
/// This is the only requirement to define as `@State`, and pass it to `SherlockForm`.
@State public var searchText: String = ""@AppStorage("username")
private var username: String = "John Appleseed"@AppStorage("language")
private var languageSelection: Int = 0@AppStorage("status")
private var status = Constant.Status.online... // Many more @AppStorage properties...
var body: some View
{
// NOTE:
// `SherlockForm` and `xxxCell` are where all the search magic is happening!
// Just treat `SherlockForm` as a normal `Form`, and use `Section` and plain SwiftUI views accordingly.
SherlockForm(searchText: $searchText) {// Simple form cells.
Section {
textCell(title: "User", value: username)
arrayPickerCell(title: "Language", selection: $languageSelection, values: Constant.languages)
casePickerCell(title: "Status", selection: $status)
toggleCell(title: "Low Power Mode", isOn: $isLowPowerOn)sliderCell(
title: "Speed",
value: $speed,
in: 0.5 ... 2.0,
step: 0.1,
maxFractionDigits: 1,
valueString: { "x\($0)" },
sliderLabel: { EmptyView() },
minimumValueLabel: { Image(systemName: "tortoise") },
maximumValueLabel: { Image(systemName: "hare") },
onEditingChanged: { print("onEditingChanged", $0) }
)stepperCell(
title: "Font Size",
value: $fontSize,
in: 8 ... 24,
step: 1,
maxFractionDigits: 0,
valueString: { "\($0) pt" }
)
}// Navigation Link Cell (`navigationLinkCell`)
Section {
navigationLinkCell(
title: "UserDefaults",
destination: { UserDefaultsListView() }
)
navigationLinkCell(
title: "App Info",
destination: { AppInfoView() }
)
navigationLinkCell(
title: "Device Info",
destination: { DeviceInfoView() }
)
navigationLinkCell(title: "Custom Page", destination: {
CustomView()
})
}// Buttons
Section {
buttonCell(
title: "Reset UserDefaults",
action: {
Helper.deleteUserDefaults()
showHUD(.init(message: "Finished resetting UserDefaults"))
}
)buttonDialogCell(
title: "Delete All Contents",
dialogTitle: nil,
dialogButtons: [
.init(title: "Delete All Contents", role: .destructive) {
try await deleteAllContents()
showHUD(.init(message: "Finished deleting all contents"))
},
.init(title: "Cancel", role: .cancel) {
print("Cancelled")
}
]
)
}
}
.navigationTitle("Settings")
// NOTE:
// Use `formCopyable` here to allow ALL `xxxCell`s to be copyable.
.formCopyable(true)
}
}
```To get started:
1. Conform your Settings view to `protocol SherlockView`
2. Add `@State var searchText: String` to your view
3. Inside view's `body`, use `SherlockForm` (just like normal `Form`), and use various built-in form components:
- Basic built-in cells
- `textCell`
- `textFieldCell`
- `textEditorCell`
- `buttonCell`
- `buttonDialogCell` (iOS 15)
- `navigationLinkCell`
- `toggleCell`
- `arrayPickerCell`
- `casePickerCell`
- `datePickerCell`
- `sliderCell`
- `stepperCell`
- List
- `simpleList`
- `nestedList`
- More customizable cells (part of `ContainerCell`)
- `hstackCell`
- `vstackCell`
4. (Optional) Attach `.formCellCopyable(true)` to each cell or entire form.
5. (Optional) Attach `.enableSherlockHUD(true)` to topmost view hierarchy to enable HUDTo customize cell's internal content view rather than cell itself,
use `.formCellContentModifier` which may solve some troubles (e.g. context menu) when customizing cells.### `SherlockHUD`
```swift
import SwiftUI
import SherlockHUD@main
struct MyApp: App
{
var body: some Scene
{
WindowGroup {
NavigationView {
RootView()
}
.enableSherlockHUD(true) // Set at the topmost view!
}
}
}@MainActor
struct RootView: View
{
/// Attaching `.enableSherlockHUD(true)` to topmost view will allow using `showHUD`.
@Environment(\.showHUD)
private var showHUD: (HUDMessage) -> Voidvar body: some View
{
VStack(spacing: 16) {
Button("Tap") {
showHUD(HUDMessage(message: "Hello SherlockForms!", duration: 2, alignment: .top))
// alignment = top / center / bottom (default)
// Can also attach custom view e.g. ProgressView. See also `HUDMessage.loading`.
}
}
.font(.largeTitle)
}
}
```See [SherlockHUD-Demo app](Examples/SherlockHUD-Demo.swiftpm) for more information.
## Acknowledgement
- [DebugMenu](https://github.com/noppefoxwolf/DebugMenu) by [@noppefoxwolf](https://github.com/noppefoxwolf) for various useful code in debugging
- [swiftui-navigation](https://github.com/pointfreeco/swiftui-navigation) by [@pointfreeco](https://github.com/pointfreeco) for making smart state-binding techniques in SwiftUI navigation
- [Custom HUDs in SwiftUI | FIVE STARS](https://www.fivestars.blog/articles/swiftui-hud/) by [Federico Zanetello](https://twitter.com/zntfdr) for easy-to-learn SwiftUI HUD development
- [@inamiy](https://github.com/inamiy)'s Wife for dedicated support during this OSS development## License
[MIT](LICENSE)