Skip to content
Snippets Groups Projects
index.js 5.21 KiB
Newer Older
import Realm from 'realm'
import { LocalDate, ChronoUnit } from 'js-joda'
import nodejs from 'nodejs-mobile-react-native'
import fs from 'react-native-fs'
import restart from 'react-native-restart'
import {
emelko's avatar
emelko committed
  cycleWithFhmMucus,
  longAndComplicatedCycleWithMucus,
  cycleWithTempAndNoMucusShift,
  cervixShiftAndFhmOnSameDay,
  longAndComplicatedCycleWithCervix,
  cycleWithTempAndNoCervixShift
} from './fixtures'
import dbSchema from './schema'
let db
const realmConfig = {
  schema: dbSchema
Julia Friesel's avatar
Julia Friesel committed
export function getBleedingDaysSortedByDate() {
  return db.objects('CycleDay').filtered('bleeding != null').sorted('date', true)
Julia Friesel's avatar
Julia Friesel committed
export function getTemperatureDaysSortedByDate() {
  return db.objects('CycleDay').filtered('temperature != null').sorted('date', true)
Julia Friesel's avatar
Julia Friesel committed
export function getCycleDaysSortedByDate() {
  return db.objects('CycleDay').sorted('date', true)
Julia Friesel's avatar
Julia Friesel committed
export function saveSymptom(symptom, cycleDay, val) {
  db.write(() => {
    cycleDay[symptom] = val
Julia Friesel's avatar
Julia Friesel committed
export function getOrCreateCycleDay(localDate) {
  let result = db.objectForPrimaryKey('CycleDay', localDate)
  if (!result) {
    db.write(() => {
      result = db.create('CycleDay', {
Julia Friesel's avatar
Julia Friesel committed
export function getCycleDay(localDate) {
  return db.objectForPrimaryKey('CycleDay', localDate)
}

Julia Friesel's avatar
Julia Friesel committed
export function fillWithMucusDummyData() {
  const dummyCycles = [
emelko's avatar
emelko committed
    cycleWithFhmMucus,
    longAndComplicatedCycleWithMucus,
    cycleWithTempAndNoMucusShift
  ]

  db.write(() => {
    db.deleteAll()
    dummyCycles.forEach(cycle => {
      cycle.forEach(day => {
        const existing = getCycleDay(day.date)
        if (existing) {
          Object.keys(day).forEach(key => {
            if (key === 'date') return
            existing[key] = day[key]
          })
        } else {
          db.create('CycleDay', day)
        }
      })
    })
Julia Friesel's avatar
Julia Friesel committed
export function fillWithCervixDummyData() {
emelko's avatar
emelko committed
  const dummyCycles = [
    cervixShiftAndFhmOnSameDay,
    longAndComplicatedCycleWithCervix,
    cycleWithTempAndNoCervixShift
emelko's avatar
emelko committed
  ]

  db.write(() => {
    db.deleteAll()
    dummyCycles.forEach(cycle => {
      cycle.forEach(day => {
        const existing = getCycleDay(day.date)
        if (existing) {
          Object.keys(day).forEach(key => {
            if (key === 'date') return
            existing[key] = day[key]
          })
        } else {
          db.create('CycleDay', day)
        }
      })
    })
  })
}

Julia Friesel's avatar
Julia Friesel committed
export function getPreviousTemperature(cycleDay) {
  cycleDay.wrappedDate = LocalDate.parse(cycleDay.date)
  const winner = getTemperatureDaysSortedByDate().find(day => {
    const wrappedDate = LocalDate.parse(day.date)
    return wrappedDate.isBefore(cycleDay.wrappedDate)
  })
  if (!winner) return null
  return winner.temperature.value
}

Julia Friesel's avatar
Julia Friesel committed
export function tryToCreateCycleDay(day, i) {
  try {
    db.create('CycleDay', day)
  } catch (err) {
    const msg = `Line ${i + 1}(${day.date}): ${err.message}`
    throw new Error(msg)
Julia Friesel's avatar
Julia Friesel committed
export function getAmountOfCycleDays() {
  const cycleDaysSortedByDate = getCycleDaysSortedByDate()
  const amountOfCycleDays = cycleDaysSortedByDate.length
  if (!amountOfCycleDays) return 0
  const earliest = cycleDaysSortedByDate[amountOfCycleDays - 1]
  const today = LocalDate.now()
  const earliestAsLocalDate = LocalDate.parse(earliest.date)
  return earliestAsLocalDate.until(today, ChronoUnit.DAYS)
}

Julia Friesel's avatar
Julia Friesel committed
export function getSchema() {
  return db.schema.reduce((acc, curr) => {
    acc[curr.name] = curr.properties
    return acc
  }, {})
}

Julia Friesel's avatar
Julia Friesel committed
export function tryToImportWithDelete(cycleDays) {
  db.write(() => {
    db.delete(db.objects('CycleDay'))
    cycleDays.forEach(tryToCreateCycleDay)
  })
}

Julia Friesel's avatar
Julia Friesel committed
export function tryToImportWithoutDelete(cycleDays) {
  db.write(() => {
    cycleDays.forEach((day, i) => {
      const existing = getCycleDay(day.date)
      if (existing) db.delete(existing)
      tryToCreateCycleDay(day, i)
    })
  })
}
export function requestHash(type, pw) {
  nodejs.channel.post('request-SHA512', JSON.stringify({
    type: type,
export async function openDb ({ hash, persistConnection }) {
Julia Friesel's avatar
Julia Friesel committed
    realmConfig.encryptionKey = hashToInt8Array(hash)
  const connection = await Realm.open(realmConfig)

  if (persistConnection) db = connection
Julia Friesel's avatar
Julia Friesel committed
export async function changeEncryptionAndRestartApp(hash) {
  let key
  if (hash) key = hashToInt8Array(hash)
  const defaultPath = db.path
  const dir = db.path.split('/')
  dir.pop()
  dir.push('copied.realm')
  const copyPath = dir.join('/')
  const exists = await fs.exists(copyPath)
  if (exists) await fs.unlink(copyPath)
Julia Friesel's avatar
Julia Friesel committed
  // for some reason, realm complains if we give it a key with value undefined
  if (key) {
    db.writeCopyTo(copyPath, key)
  } else {
    db.writeCopyTo(copyPath)
  }
Julia Friesel's avatar
Julia Friesel committed
  await fs.unlink(defaultPath)
  await fs.moveFile(copyPath, defaultPath)
Julia Friesel's avatar
Julia Friesel committed
export async function deleteDbAndOpenNew() {
  const exists = await fs.exists(Realm.defaultPath)
  if (exists) await fs.unlink(Realm.defaultPath)
  await openDb({ persistConnection: true })
Julia Friesel's avatar
Julia Friesel committed
}

function hashToInt8Array(hash) {
  const key = new Uint8Array(64)
  for (let i = 0; i < key.length; i++) {
    const twoDigitHex = hash.slice(i * 2, i * 2 + 2)
    key[i] = parseInt(twoDigitHex, 16)
  }
  return key