Skip to content

Commit

Permalink
SwiftFirebase: initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
compnerd committed Aug 10, 2023
0 parents commit de2102c
Show file tree
Hide file tree
Showing 31 changed files with 1,648 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.gitattributes eol=lf
.gitignore eol=lf
*.hh eol=lf
*.json eol=lf
*.plist eol=lf
*.swift eol=lf
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.sw?
.build/
.vscode/
Examples/FireBaseUI/Resources/google-services-desktop.json
37 changes: 37 additions & 0 deletions Examples/FireBaseUI/FireBaseUI.exe.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<asmv1:assembly
manifestVersion="1.0"
xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">

<!-- assembly identity -->
<asmv1:assemblyIdentity
name="org.compnerd.SwiftFirebase.FireBaseUI"
processorArchitecture="*"
type="win32"
version="1.0.0.0"/>

<!-- application specific settings -->
<asmv3:application xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
<windowsSettings>
<dpiAwareness xmlns="">PerMonitorV2</dpiAwareness>
<dpiAware>true</dpiAware>
</windowsSettings>
</asmv3:application>

<asmv1:description>FireBaseUI</asmv1:description>

<!-- Common Control Support -->
<asmv1:dependency>
<asmv1:dependentAssembly>
<asmv1:assemblyIdentity
language="*"
name="Microsoft.Windows.Common-Controls"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
type="win32"
version="6.0.0.0"
/>
</asmv1:dependentAssembly>
</asmv1:dependency>
</asmv1:assembly>
30 changes: 30 additions & 0 deletions Examples/FireBaseUI/FireBaseUI.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: BSD-3-Clause

import SwiftWin32
import Foundation

import firebase
import FirebaseCore
import FirebaseAuth

extension Foundation.Bundle {
internal static var resources: URL {
Bundle.module.bundleURL.appendingPathComponent("Resources")
}
}

@main
final class FireBaseUI: ApplicationDelegate {
func application(_ application: Application,
didFinishLaunchingWithOptions: [Application.LaunchOptionsKey:Any]?)
-> Bool {
#if _runtime(_ObjC)
firebase.App.SetDefaultConfigPath(Bundle.resources.fileSystemRepresentation)
#else
Bundle.resources.withUnsafeFileSystemRepresentation(firebase.App.SetDefaultConfigPath)
#endif

FirebaseApp.configure()
return true
}
}
199 changes: 199 additions & 0 deletions Examples/FireBaseUI/FireBaseUIViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// SPDX-License-Identifier: BSD-3-Clause

import firebase
import FirebaseCore
import FirebaseAuth
import SwiftWin32

private final class FireBaseLogLevelPickerHandler {
private let levels = ["Default", "Verbose", "Debug", "Info", "Warning", "Error", "Assert"]
}

extension FireBaseLogLevelPickerHandler: PickerViewDataSource {
public func numberOfComponents(in pickerView: PickerView) -> Int {
1
}

public func pickerView(_ pickerView: PickerView,
numberOfRowsInComponent component: Int) -> Int {
self.levels.count
}
}

extension FireBaseLogLevelPickerHandler: PickerViewDelegate {
public func pickerView(_ pickerView: PickerView, titleForRow row: Int,
forComponent component: Int) -> String? {
self.levels[row]
}

public func pickerView(_ pickerView: PickerView, didSelectRow row: Int,
inComponent component: Int) {
guard row > 0 else { return }
FirebaseConfiguration.shared.setLoggerLevel(FirebaseLoggerLevel(rawValue: CInt(row - 1)))
}
}

// MARK: - FireBaseUIViewController

internal final class FireBaseUIViewController: ViewController {
fileprivate let firebaseLogHandler = FireBaseLogLevelPickerHandler()

var cboLogLevel = PickerView(frame: Rect(x: 136, y: 8, width: 256, height: 24))
var txtEmail = TextField(frame: Rect(x: 136, y: 46, width: 512, height: 24))
var txtPassword = TextField(frame: Rect(x: 136, y: 78, width: 512, height: 24))
var btnSignIn = Button(frame: Rect(x: 8, y: 116, width: 120, height: 32),
title: "Sign In")
var btnToken = Button(frame: Rect(x: 8, y: 180, width: 120, height: 32),
title: "Get Token")
var chkRefresh = Switch(frame: Rect(x: 8, y: 212, width: 648, height: 32),
title: "Force Token Refresh")
var txtToken: TextView = TextView(frame: Rect(x: 8, y: 244, width: 640, height: 48))

var btnCreate = Button(frame: Rect(x: 8, y: 324, width: 120, height: 32),
title: "Create User")
var btnVerify = Button(frame: Rect(x: 132, y: 324, width: 120, height: 32),
title: "Verify Email")
var btnReset = Button(frame: Rect(x: 256, y: 324, width: 156, height: 32),
title: "Reset Password")

override func viewDidLoad() {
super.viewDidLoad()
self.title = "FireBase UI"
configureView()

if let user = Auth.auth().currentUser {
txtEmail.text = user.email
try? Auth.auth().signOut()
}
}

private func configureView() {
let lblLogLevel = Label(frame: Rect(x: 8, y: 8, width: 128, height: 24),
title: "Log Level:")
self.view?.addSubview(lblLogLevel)

cboLogLevel.dataSource = firebaseLogHandler
cboLogLevel.delegate = firebaseLogHandler
self.view?.addSubview(cboLogLevel)
cboLogLevel.reloadAllComponents()
cboLogLevel.selectRow(0, inComponent: 0, animated: false)

let lblEmail = Label(frame: Rect(x: 8, y: 46, width: 128, height: 20),
title: "Email Address:")
self.view?.addSubview(lblEmail)
self.view?.addSubview(txtEmail)

let lblPassword = Label(frame: Rect(x: 8, y: 78, width: 128, height: 20),
title: "Password:")
self.view?.addSubview(lblPassword)

txtPassword.isSecureTextEntry = true
self.view?.addSubview(txtPassword)

btnSignIn.addTarget(self, action: FireBaseUIViewController.signIn,
for: .primaryActionTriggered)
self.view?.addSubview(btnSignIn)

btnToken.addTarget(self, action: FireBaseUIViewController.getToken,
for: .primaryActionTriggered)
self.view?.addSubview(btnToken)

self.view?.addSubview(chkRefresh)

txtToken.editable = false
txtToken.font = .systemFont(ofSize: 9)
self.view?.addSubview(txtToken)

btnCreate.addTarget(self, action: FireBaseUIViewController.createUser,
for: .primaryActionTriggered)
self.view?.addSubview(btnCreate)

btnVerify.addTarget(self, action: FireBaseUIViewController.verifyEmail,
for: .primaryActionTriggered)
self.view?.addSubview(btnVerify)

btnReset.addTarget(self, action: FireBaseUIViewController.resetPassword,
for: .primaryActionTriggered)
self.view?.addSubview(btnReset)
}

private func signIn() {
guard let email = txtEmail.text, let password = txtPassword.text else {
print("email and password are required")
return
}

Task {
do {
_ = try await Auth.auth().signIn(withEmail: email, password: password)
} catch {
print("Error signing in: \(error.localizedDescription)")
}
}
}

private func createUser() {
guard let email = txtEmail.text, let password = txtPassword.text else {
print("email and password are required")
return
}

Task {
do {
_ = try await Auth.auth().createUser(withEmail: email, password: password)
} catch {
print("Error signing in: \(error.localizedDescription)")
}
}
}

private func getToken() {
Task {
guard var user = Auth.auth().currentUser else {
print("user not logged in")
return
}

if chkRefresh.isOn {
do {
let result = try await user.getIDTokenResult(forcingRefresh: true)
txtToken.text = result.token
} catch {
print("Error refreshing token: \(error.localizedDescription)")
}
} else {
do {
txtToken.text = try await user.getIDToken()
} catch {
print("Error refreshing token: \(error.localizedDescription)")
}
}
}
}

private func verifyEmail() {
Task {
guard var user = Auth.auth().currentUser else {
print("user not logged in")
return
}

try await user.sendEmailVerification()
}
}

private func resetPassword() {
guard let email = txtEmail.text else {
print("email is required")
return
}

Task {
do {
_ = try await Auth.auth().sendPasswordReset(withEmail: email)
} catch {
print("Error sending password reset: \(error.localizedDescription)")
}
}
}
}
25 changes: 25 additions & 0 deletions Examples/FireBaseUI/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>org.compnerd.SwiftFirebase.FireBaseUI</string>
<key>ApplicationSceneManifest</key>
<dict>
<key>ApplicationSupportsMultipleScenes</key>
<false/>
<key>SceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>SceneConfigurationName</key>
<string>Default Configuration</string>
<key>SceneDelegateClassName</key>
<string>FireBaseUI.SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>
20 changes: 20 additions & 0 deletions Examples/FireBaseUI/Resources/google-services.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"project_info": {
"project_id": "test-do-not-use",
"firebase_url": "https://test-do-not-use.firebaseio.com",
"storage_bucket": "test-do-not-use.firebaseio.com"
},
"client": [
{
"api_key": [
{ "current_key": "000000000000000000000000000000000000000" }
],
"client_info": {
"mobilesdk_app_id": "1:999999999999:ios:0000000000000000",
"android_client_info": {
"package_name": "com.firebaseio.test-do-not-use"
}
}
}
]
}
16 changes: 16 additions & 0 deletions Examples/FireBaseUI/SceneDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: BSD-3-Clause

import SwiftWin32

final class SceneDelegate: WindowSceneDelegate {
var window: Window?

func scene(_ scene: Scene, willConnectTo session: SceneSession,
options: Scene.ConnectionOptions) {
guard let windowScene = scene as? WindowScene else { return }

self.window = Window(windowScene: windowScene)
self.window?.rootViewController = FireBaseUIViewController()
self.window?.makeKeyAndVisible()
}
}
24 changes: 24 additions & 0 deletions Examples/FireBaseUI/SwiftWin32+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: BSD-3-Clause

import SwiftWin32

extension Button {
internal convenience init(frame: Rect, title: String) {
self.init(frame: frame)
self.setTitle(title, forState: .normal)
}
}

extension Label {
internal convenience init(frame: Rect, title: String) {
self.init(frame: frame)
self.text = title
}
}

extension Switch {
internal convenience init(frame: Rect, title: String) {
self.init(frame: frame)
self.title = title
}
}
28 changes: 28 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
BSD 3-Clause License

Copyright (c) 2023, Saleem Abdulrasool

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Loading

0 comments on commit de2102c

Please sign in to comment.