mirror of https://github.com/iSoron/uhabits.git
parent
7cab0a39e5
commit
a546f6de73
Binary file not shown.
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.models
|
||||
|
||||
import org.isoron.uhabits.utils.Database
|
||||
import org.isoron.uhabits.utils.StepResult
|
||||
|
||||
class HabitList(var db: Database) {
|
||||
var habits = mutableListOf<Habit>()
|
||||
|
||||
init {
|
||||
loadHabitsFromDatabase()
|
||||
}
|
||||
|
||||
fun getActive(): List<Habit> {
|
||||
return habits.filter { h -> !h.isArchived }
|
||||
}
|
||||
|
||||
private fun loadHabitsFromDatabase() {
|
||||
val stmt = db.prepareStatement(
|
||||
"select id, name, description, freq_num, freq_den, color, " +
|
||||
"archived, position, unit, target_value, type " +
|
||||
"from habits")
|
||||
|
||||
while (stmt.step() == StepResult.ROW) {
|
||||
habits.add(Habit(id = stmt.getInt(0),
|
||||
name = stmt.getText(1),
|
||||
description = stmt.getText(2),
|
||||
frequency = Frequency(stmt.getInt(3),
|
||||
stmt.getInt(4)),
|
||||
color = Color(stmt.getInt(5)),
|
||||
isArchived = (stmt.getInt(6) != 0),
|
||||
position = stmt.getInt(7),
|
||||
unit = stmt.getText(8),
|
||||
target = 0,
|
||||
type = HabitType.YES_NO_HABIT))
|
||||
}
|
||||
stmt.finalize()
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.models
|
||||
|
||||
import org.isoron.uhabits.utils.Database
|
||||
import org.isoron.uhabits.utils.PreparedStatement
|
||||
import org.isoron.uhabits.utils.StepResult
|
||||
import org.isoron.uhabits.utils.nextId
|
||||
|
||||
class HabitRepository(var db: Database) {
|
||||
|
||||
companion object {
|
||||
const val SELECT_COLUMNS = "id, name, description, freq_num, freq_den, color, archived, position, unit, target_value, type"
|
||||
const val SELECT_PLACEHOLDERS = "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?"
|
||||
const val UPDATE_COLUMNS = "id=?, name=?, description=?, freq_num=?, freq_den=?, color=?, archived=?, position=?, unit=?, target_value=?, type=?"
|
||||
}
|
||||
|
||||
private val findAllStatement = db.prepareStatement("select $SELECT_COLUMNS from habits order by position")
|
||||
private val insertStatement = db.prepareStatement("insert into Habits($SELECT_COLUMNS) values ($SELECT_PLACEHOLDERS)")
|
||||
private val updateStatement = db.prepareStatement("update Habits set $UPDATE_COLUMNS where id=?")
|
||||
private val deleteStatement = db.prepareStatement("delete from Habits where id=?")
|
||||
|
||||
fun nextId(): Int {
|
||||
return db.nextId("Habits")
|
||||
}
|
||||
|
||||
fun findAll(): MutableMap<Int, Habit> {
|
||||
val result = mutableMapOf<Int, Habit>()
|
||||
while (findAllStatement.step() == StepResult.ROW) {
|
||||
val habit = buildHabitFromStatement(findAllStatement)
|
||||
result[habit.id] = habit
|
||||
}
|
||||
findAllStatement.reset()
|
||||
return result
|
||||
}
|
||||
|
||||
fun insert(habit: Habit) {
|
||||
bindHabitToStatement(habit, insertStatement)
|
||||
insertStatement.step()
|
||||
insertStatement.reset()
|
||||
}
|
||||
|
||||
fun update(habit: Habit) {
|
||||
bindHabitToStatement(habit, updateStatement)
|
||||
updateStatement.bindInt(11, habit.id)
|
||||
updateStatement.step()
|
||||
updateStatement.reset()
|
||||
}
|
||||
|
||||
private fun buildHabitFromStatement(stmt: PreparedStatement): Habit {
|
||||
return Habit(id = stmt.getInt(0),
|
||||
name = stmt.getText(1),
|
||||
description = stmt.getText(2),
|
||||
frequency = Frequency(stmt.getInt(3), stmt.getInt(4)),
|
||||
color = Color(stmt.getInt(5)),
|
||||
isArchived = stmt.getInt(6) != 0,
|
||||
position = stmt.getInt(7),
|
||||
unit = stmt.getText(8),
|
||||
target = stmt.getReal(9),
|
||||
type = if (stmt.getInt(10) == 0) HabitType.YES_NO_HABIT else HabitType.NUMERICAL_HABIT)
|
||||
}
|
||||
|
||||
private fun bindHabitToStatement(habit: Habit, statement: PreparedStatement) {
|
||||
statement.bindInt(0, habit.id)
|
||||
statement.bindText(1, habit.name)
|
||||
statement.bindText(2, habit.description)
|
||||
statement.bindInt(3, habit.frequency.numerator)
|
||||
statement.bindInt(4, habit.frequency.denominator)
|
||||
statement.bindInt(5, habit.color.paletteIndex)
|
||||
statement.bindInt(6, if (habit.isArchived) 1 else 0)
|
||||
statement.bindInt(7, habit.position)
|
||||
statement.bindText(8, habit.unit)
|
||||
statement.bindReal(9, habit.target)
|
||||
statement.bindInt(10, habit.type.code)
|
||||
}
|
||||
|
||||
fun delete(habit: Habit) {
|
||||
deleteStatement.bindInt(0, habit.id)
|
||||
deleteStatement.step()
|
||||
deleteStatement.reset()
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.utils
|
||||
|
||||
import platform.Foundation.*
|
||||
|
||||
class IosResourceFile(val path: String) : ResourceFile {
|
||||
private val fileManager = NSFileManager.defaultManager()
|
||||
override fun readLines(): List<String> {
|
||||
val contents = NSString.stringWithContentsOfFile(path) as NSString
|
||||
return contents.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()) as List<String>
|
||||
}
|
||||
}
|
||||
|
||||
class IosUserFile(val path: String) : UserFile {
|
||||
override fun exists(): Boolean {
|
||||
return NSFileManager.defaultManager().fileExistsAtPath(path)
|
||||
}
|
||||
|
||||
override fun delete() {
|
||||
NSFileManager.defaultManager().removeItemAtPath(path, null)
|
||||
}
|
||||
}
|
||||
|
||||
class IosFileOpener : FileOpener {
|
||||
override fun openResourceFile(filename: String): ResourceFile {
|
||||
val root = NSBundle.mainBundle.resourcePath!!
|
||||
return IosResourceFile("$root/$filename")
|
||||
}
|
||||
|
||||
override fun openUserFile(filename: String): UserFile {
|
||||
val manager = NSFileManager.defaultManager()
|
||||
val root = manager.URLForDirectory(NSDocumentDirectory,
|
||||
NSUserDomainMask,
|
||||
null, false, null)!!.path
|
||||
return IosUserFile("$root/$filename")
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.models
|
||||
|
||||
import junit.framework.Assert.assertEquals
|
||||
import org.isoron.uhabits.BaseTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class HabitRepositoryTest : BaseTest() {
|
||||
lateinit var repository: HabitRepository
|
||||
|
||||
lateinit private var original0: Habit
|
||||
lateinit private var original1: Habit
|
||||
lateinit private var original2: Habit
|
||||
|
||||
@Before
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
|
||||
original0 = Habit(id = 0,
|
||||
name = "Wake up early",
|
||||
description = "Did you wake up before 6am?",
|
||||
frequency = Frequency(1, 1),
|
||||
color = Color(3),
|
||||
isArchived = false,
|
||||
position = 0,
|
||||
unit = "",
|
||||
target = 0.0,
|
||||
type = HabitType.YES_NO_HABIT)
|
||||
|
||||
original1 = Habit(id = 1,
|
||||
name = "Exercise",
|
||||
description = "Did you exercise for at least 20 minutes?",
|
||||
frequency = Frequency(1, 2),
|
||||
color = Color(4),
|
||||
isArchived = false,
|
||||
position = 1,
|
||||
unit = "",
|
||||
target = 0.0,
|
||||
type = HabitType.YES_NO_HABIT)
|
||||
|
||||
original2 = Habit(id = 2,
|
||||
name = "Learn Japanese",
|
||||
description = "Did you study Japanese today?",
|
||||
frequency = Frequency(1, 1),
|
||||
color = Color(3),
|
||||
isArchived = false,
|
||||
position = 2,
|
||||
unit = "",
|
||||
target = 0.0,
|
||||
type = HabitType.YES_NO_HABIT)
|
||||
|
||||
repository = HabitRepository(db)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFindActive() {
|
||||
var habits = repository.findAll()
|
||||
assertEquals(0, repository.nextId())
|
||||
assertEquals(0, habits.size)
|
||||
|
||||
repository.insert(original0)
|
||||
repository.insert(original1)
|
||||
repository.insert(original2)
|
||||
habits = repository.findAll()
|
||||
assertEquals(3, habits.size)
|
||||
assertEquals(original0, habits[0])
|
||||
assertEquals(original1, habits[1])
|
||||
assertEquals(original2, habits[2])
|
||||
|
||||
assertEquals(3, repository.nextId())
|
||||
|
||||
original0.description = "New description"
|
||||
repository.update(original0)
|
||||
habits = repository.findAll()
|
||||
assertEquals(original0, habits[0])
|
||||
|
||||
repository.delete(original0)
|
||||
habits = repository.findAll()
|
||||
assertEquals(2, habits.size)
|
||||
assertEquals(original1, habits[1])
|
||||
assertEquals(original2, habits[2])
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"size" : "1024x1024",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
|
||||
class EditHabitTableViewController: NSObject, UITableViewDataSource, UITableViewDelegate {
|
||||
func disclosure(title: String, subtitle: String) -> UITableViewCell {
|
||||
let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
|
||||
cell.textLabel?.text = title
|
||||
cell.detailTextLabel?.text = subtitle
|
||||
cell.accessoryType = .disclosureIndicator
|
||||
return cell
|
||||
}
|
||||
|
||||
func input(title: String) -> UITableViewCell {
|
||||
let cell = UITableViewCell()
|
||||
let field = UITextField(frame: cell.bounds.insetBy(dx: 20, dy: 0))
|
||||
field.placeholder = title
|
||||
field.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth,
|
||||
UIView.AutoresizingMask.flexibleHeight]
|
||||
cell.contentView.addSubview(field)
|
||||
return cell
|
||||
}
|
||||
|
||||
var primary = [UITableViewCell]()
|
||||
var secondary = [UITableViewCell]()
|
||||
var parentController: EditHabitController
|
||||
|
||||
init(withParentController parentController: EditHabitController) {
|
||||
self.parentController = parentController
|
||||
super.init()
|
||||
primary.append(input(title: "Name"))
|
||||
primary.append(input(title: "Question (e.g. Did you wake up early today?)"))
|
||||
secondary.append(disclosure(title: "Color", subtitle: "Blue"))
|
||||
secondary.append(disclosure(title: "Repeat", subtitle: "Daily"))
|
||||
secondary.append(disclosure(title: "Reminder", subtitle: "Disabled"))
|
||||
}
|
||||
|
||||
func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return section == 0 ? primary.count : secondary.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
return indexPath.section == 0 ? primary[indexPath.item] : secondary[indexPath.item]
|
||||
}
|
||||
|
||||
// func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
// let alert = UIAlertController(title: "Hello", message: "You selected something", preferredStyle: .alert)
|
||||
// parentController.present(alert, animated: true)
|
||||
// }
|
||||
}
|
||||
|
||||
class EditHabitController: UIViewController {
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
let bounds = UIScreen.main.bounds
|
||||
let tableController = EditHabitTableViewController(withParentController: self)
|
||||
let table = UITableView(frame: bounds, style: .grouped)
|
||||
table.dataSource = tableController
|
||||
table.delegate = tableController
|
||||
self.view = table
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
self.title = "Edit Habit"
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?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>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>Launch.storyboard</string>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13142" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12042"/>
|
||||
</dependencies>
|
||||
<scenes/>
|
||||
</document>
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
|
||||
class ListHabitsController: UIViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
self.title = "Habits"
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add,
|
||||
target: self,
|
||||
action: #selector(self.onCreateHabitClicked))
|
||||
|
||||
// let box = UIView(frame: view.bounds.insetBy(dx: 100, dy: 100))
|
||||
// box.backgroundColor = .blue
|
||||
//// box.translatesAutoresizingMaskIntoConstraints = true
|
||||
// box.autoresizingMask = [UIView.AutoresizingMask.flexibleLeftMargin,
|
||||
// UIView.AutoresizingMask.flexibleRightMargin]
|
||||
// view.addSubview(box)
|
||||
}
|
||||
|
||||
@objc func onCreateHabitClicked() {
|
||||
self.navigationController?.pushViewController(EditHabitController(), animated: true)
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?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>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
class IosResourceFile : NSObject, ResourceFile {
|
||||
|
||||
var path: String
|
||||
|
||||
var fileManager = FileManager.default
|
||||
|
||||
init(forPath path: String) {
|
||||
self.path = path
|
||||
}
|
||||
|
||||
func readLines() -> [String] {
|
||||
do {
|
||||
let contents = try String(contentsOfFile: self.path, encoding: .utf8)
|
||||
return contents.components(separatedBy: CharacterSet.newlines)
|
||||
} catch {
|
||||
return [""]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IosUserFile : NSObject, UserFile {
|
||||
|
||||
var path: String
|
||||
|
||||
init(forPath path: String) {
|
||||
self.path = path
|
||||
}
|
||||
|
||||
func delete() {
|
||||
do {
|
||||
try FileManager.default.removeItem(atPath: path)
|
||||
} catch {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func exists() -> Bool {
|
||||
return FileManager.default.fileExists(atPath: path)
|
||||
}
|
||||
}
|
||||
|
||||
class IosFileOpener : NSObject, FileOpener {
|
||||
func openResourceFile(filename: String) -> ResourceFile {
|
||||
let path = "\(Bundle.main.resourcePath!)/\(filename)"
|
||||
return IosResourceFile(forPath: path)
|
||||
}
|
||||
|
||||
func openUserFile(filename: String) -> UserFile {
|
||||
do {
|
||||
let root = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).path
|
||||
return IosUserFile(forPath: "\(root)/\(filename)")
|
||||
} catch {
|
||||
return IosUserFile(forPath: "invalid")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
TextInput,
|
||||
View,
|
||||
Text,
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
TouchableHighlight,
|
||||
} from 'react-native';
|
||||
import FontAwesome from '../../helpers/FontAwesome';
|
||||
import { Colors } from '../../helpers/Colors';
|
||||
import ColorCircle from '../common/ColorCircle';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: Colors.appBackground,
|
||||
flex: 1,
|
||||
},
|
||||
item: {
|
||||
fontSize: 17,
|
||||
paddingTop: 15,
|
||||
paddingBottom: 15,
|
||||
paddingRight: 15,
|
||||
paddingLeft: 15,
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
label: {
|
||||
fontSize: 17,
|
||||
flex: 1,
|
||||
},
|
||||
value: {
|
||||
fontSize: 17,
|
||||
},
|
||||
multiline: {
|
||||
},
|
||||
middle: {
|
||||
borderBottomColor: Colors.headerBorderColor,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
},
|
||||
section: {
|
||||
backgroundColor: Colors.appBackground,
|
||||
marginTop: 30,
|
||||
borderTopColor: Colors.headerBorderColor,
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderBottomColor: Colors.headerBorderColor,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
},
|
||||
icon: {
|
||||
fontFamily: 'FontAwesome',
|
||||
color: Colors.unchecked,
|
||||
marginLeft: 10,
|
||||
fontSize: 12,
|
||||
paddingTop: 2,
|
||||
},
|
||||
text: {
|
||||
borderWidth: 1,
|
||||
padding: 25,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
});
|
||||
|
||||
export default class EditHabitsScene extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<ScrollView style={styles.container}>
|
||||
<View style={styles.section}>
|
||||
<TextInput
|
||||
autoFocus
|
||||
style={[styles.item, styles.middle, { color: Colors[1] }]}
|
||||
placeholder="Name"
|
||||
/>
|
||||
<TextInput
|
||||
style={[styles.item]}
|
||||
placeholder="Question (e.g. Did you exercise today?)"
|
||||
multiline
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.section}>
|
||||
<TouchableHighlight onPress={() => {}}>
|
||||
<View style={[styles.item, styles.middle]}>
|
||||
<Text style={styles.label}>Color</Text>
|
||||
<ColorCircle size={20} color={Colors[1]} />
|
||||
<Text style={styles.icon}>{FontAwesome.chevronRight}</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
<TouchableHighlight onPress={() => {}}>
|
||||
<View style={[styles.item, styles.middle]}>
|
||||
<Text style={styles.label}>Repeat</Text>
|
||||
<Text style={styles.value}>Every Day</Text>
|
||||
<Text style={styles.icon}>{FontAwesome.chevronRight}</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
<TouchableHighlight onPress={() => {}}>
|
||||
<View style={[styles.item, styles.middle]}>
|
||||
<Text style={styles.label}>Reminder</Text>
|
||||
<Text style={styles.value}>12:30</Text>
|
||||
<Text style={styles.icon}>{FontAwesome.chevronRight}</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
module.exports = {
|
||||
check: '\uf00c',
|
||||
times: '\uf00d',
|
||||
chevronRight: '\uf054',
|
||||
};
|
||||
|
Loading…
Reference in new issue