![moko-resources](img/logo.png)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0) [![Download](https://img.shields.io/maven-central/v/dev.icerock.moko/resources) ](https://repo1.maven.org/maven2/dev/icerock/moko/resources) ![kotlin-version](https://kotlin-version.aws.icerock.dev/kotlin-version?group=dev.icerock.moko&name=resources)
![badge][badge-android]
![badge][badge-iosX64]
![badge][badge-iosArm64]
![badge][badge-iosSimulatorArm64]
![badge][badge-macosArm64]
![badge][badge-macosX64]
![badge][badge-jvm]
![badge][badge-js]

# Mobile Kotlin resources

This is a Kotlin MultiPlatform library (and Gradle plugin) that provides access to the resources on
macOS, iOS, Android the JVM and JS/Browser with the support of the default system localization.

Also MOKO resources
supports [Compose Multiplatform](https://github.com/JetBrains/compose-multiplatform) so you can
implement all your UI in Kotlin with Jetpack Compose and MOKO resources.

## Table of Contents

- [Features](#features)
- [Requirements](#requirements)
- [Versions](#versions)
- [Installation](#installation)
- [Usage](#usage)
- [Samples](#samples)
- [Set Up Locally](#set-up-locally)
- [Contributing](#contributing)
- [License](#license)

## Features

- **Strings, Plurals** to access the corresponding resources from common code;
- **Colors** with light/dark mode support;
- **Compose Multiplatform** support;
- **Images** support (`svg`, `png`, `jpg`) with light/dark mode support;
- **Fonts** support (`ttf`, `otf`);
- **Files** support (as `raw` or `assets` for android);
- **StringDesc** for lifecycle-aware access to resources and unified localization on both platforms;
- **Static** iOS frameworks support;
- **Fat and XC** frameworks support.

## Requirements

- Gradle version 7.5+
- Kotlin 1.9.20+
- Android Gradle Plugin 7.4.2+
- Android API 16+
- iOS version 11.0+
- Compose Multiplatform 1.6.0+

## Installation

### Gradle setup

root build.gradle

```groovy
buildscript {
    repositories {
        gradlePluginPortal()
    }

    dependencies {
        classpath "dev.icerock.moko:resources-generator:0.24.1"
    }
}

allprojects {
    repositories {
        mavenCentral()
    }
}
```

project build.gradle

```groovy
apply plugin: "dev.icerock.mobile.multiplatform-resources"

dependencies {
    commonMainApi("dev.icerock.moko:resources:0.24.1")
    commonMainApi("dev.icerock.moko:resources-compose:0.24.1") // for compose multiplatform

    commonTestImplementation("dev.icerock.moko:resources-test:0.24.1")
}

multiplatformResources {
    resourcesPackage.set("org.example.library") // required
    resourcesClassName.set("SharedRes") // optional, default MR
    resourcesVisibility.set(MRVisibility.Internal) // optional, default Public
    iosBaseLocalizationRegion.set("en") // optional, default "en"
    iosMinimalDeploymentTarget.set("11.0") // optional, default "9.0"
}
```

#### Custom resource sourceSet

If you need custom path for source of resources, you need add in plugin configuration resourcesSourceSets option:
project build.gradle

```groovy
multiplatformResources {
    resourcesPackage.set("org.example.library.customResource") // required
    resourcesSourceSets {
        getByName("jvmMain").srcDirs(
            File(projectDir, "customResources")
        )
    }
}
```

On next step, you must create inside of project directory folder with name: `customResources`, and moved your resources there.

```
- projectDirectory
-- customResources
--- assets
--- base
--- image
```

Example of custom sourceSet in: `resources-gallery` sample, inside `jvm-app`

#### Export classes to Swift

To use `toUIColor()`, `toUIImage()`, `desc()` and other iOS extensions from Swift - you
should [add `export` declarations](https://kotlinlang.org/docs/multiplatform-build-native-binaries.html#export-dependencies-to-binaries):

```
framework {
    export("dev.icerock.moko:resources:0.24.1")
    export("dev.icerock.moko:graphics:0.9.0") // toUIColor here
}
```

#### Multi-module Gradle projects

If you have multiple gradle modules and resources stored not in module that compiles into framework for iOS, for example:
```
- shared
-- resources
-- feature-1
-- feature-2
```
You should enable moko-resources gradle plugin in `resources` module, that contains resources, AND in `shared` module, that compiles into framework for iOS (same for jvm, JS, macos targets. Only android will works without this).

### Xcode setup

For correct work of plugin tasks you need disable `ENABLE_USER_SCRIPT_SANDBOXING` in .xcodeproj file:
Xcode > Build Settings > Build Options > User Script Sandbox set `NO`

In iOS/macOS Info.plist need to add localizations, to use localizations strings.

```xml

<key>CFBundleLocalizations</key><array>
<string>en</string>
<string>ru</string>
</array>
```

in array should be added all used languages.

### Android build types

If your project includes a build type, for example `staging` which isn't in moko-resources. That
isn't an issue. Use matchingFallbacks to specify alternative matches for a given build type, as
shown below

```
buildTypes {
    staging {
        initWith debug
        matchingFallbacks = ['debug']
    }
}
```

### JS Webpack

JS/Browser generates json files which is included in webpack by default.
For more details about JS see `samples/resources-gallery/web-app` sample

### iOS/macOS static kotlin frameworks support

Static framework can't have own resources, so we should setup additional `Build Phase` in Xcode
that will copy resources to application.

> **⚠ Warning**
>
> This phase should be placed after Kotlin Framework Compilation phase.

Please replace `:yourframeworkproject` to kotlin project gradle path, and set correct relative
path (`$SRCROOT/../` in example).

#### With org.jetbrains.kotlin.native.cocoapods

In Xcode add `Build Phase` (at end of list) with script:

```shell script
"$SRCROOT/../gradlew" -p "$SRCROOT/../" :yourframeworkproject:copy`YourFrameworkName`FrameworkResourcesToApp \
    -Pmoko.resources.BUILT_PRODUCTS_DIR="$BUILT_PRODUCTS_DIR" \
    -Pmoko.resources.CONTENTS_FOLDER_PATH="$CONTENTS_FOLDER_PATH" \
    -Pkotlin.native.cocoapods.platform="$PLATFORM_NAME" \
    -Pkotlin.native.cocoapods.archs="$ARCHS" \
    -Pkotlin.native.cocoapods.configuration="$CONFIGURATION"
```

`YourFrameworkName` is name of your project framework. Please, see on a static framework warning for get correct task name.

#### Without org.jetbrains.kotlin.native.cocoapods

In Xcode add `Build Phase` (at end of list) with script:

```shell script
"$SRCROOT/../gradlew" -p "$SRCROOT/../" :yourframeworkproject:copyFrameworkResourcesToApp \
    -Pmoko.resources.PLATFORM_NAME="$PLATFORM_NAME" \
    -Pmoko.resources.CONFIGURATION="$CONFIGURATION" \
    -Pmoko.resources.ARCHS="$ARCHS" \
    -Pmoko.resources.BUILT_PRODUCTS_DIR="$BUILT_PRODUCTS_DIR" \
    -Pmoko.resources.CONTENTS_FOLDER_PATH="$CONTENTS_FOLDER_PATH"
```

#### Disable warning about static framework usage

To disable warnings about static framework in gradle.properties:

```xml
moko.resources.disableStaticFrameworkWarning=false
```

### iOS executable

When you use `executable` kotlin target you should add custom build phase to xcode, after kotlin
compilation:

```shell
"$SRCROOT/../gradlew" -p "$SRCROOT/../" :shared:copyResourcesDebugExecutableIosSimulatorArm64 \
    -Pmoko.resources.BUILT_PRODUCTS_DIR=$BUILT_PRODUCTS_DIR \
    -Pmoko.resources.CONTENTS_FOLDER_PATH=$CONTENTS_FOLDER_PATH
```

`copyResourcesDebugExecutableIosSimulatorArm64` should be configured depends on target.

Configured sample you can see in `samples/kotlin-ios-app`

### Creating Fat Framework with resources

Just
use `FatFrameworkTask` [from kotlin plugin](https://kotlinlang.org/docs/mpp-build-native-binaries.html#build-universal-frameworks)
.

### Creating XCFramework with resources

Just
use `XCFramework` [from kotlin plugin](https://kotlinlang.org/docs/mpp-build-native-binaries.html#build-xcframeworks)
.

But if you use **static frameworks** required additional setup - add to Xcode build phase (at end):

```bash
"$SRCROOT/../gradlew" -p "$SRCROOT/../" :shared:copyResourcesMultiPlatformLibraryReleaseXCFrameworkToApp \
    -Pmoko.resources.BUILT_PRODUCTS_DIR=$BUILT_PRODUCTS_DIR \
    -Pmoko.resources.CONTENTS_FOLDER_PATH=$CONTENTS_FOLDER_PATH
```

and add in your build.gradle config:
```kotlin
multiplatformResources {
    configureCopyXCFrameworkResources("MultiPlatformLibrary")
}
```

replace "MultiPlatformLibrary" with name that you use in `XCFramework` creation.

Details you can check in sample `samples/ios-static-xcframework`.

## Usage

### Example 1 - simple localization string

The first step is a create a file `strings.xml` in `commonMain/moko-resources/base` with the following
content:

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
    <string name="my_string">My default localization string</string>
</resources>
```

Next - create a file `strings.xml` with localized strings
in `commonMain/moko-resources/<languageCode>`. Here's an example of
creating `commonMain/moko-resources/ru` for a Russian localization:

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
    <string name="my_string">Моя строка локализации по умолчанию</string>
</resources>
```

After adding the resources we can call a gradle sync or execute a gradle
task `generateMRcommonMain`. This will generate a `MR` class containing `MR.strings.my_string`,
which we can use in `commonMain`:

```kotlin
fun getMyString(): StringDesc {
    return StringDesc.Resource(MR.strings.my_string)
}
```

After this we can use our functions on the platform side:
Android:

```kotlin
val string = getMyString().toString(context = this)
```

iOS:

```swift
let string = getMyString().localized()
```

JS:

```kotlin
val strings = MR.stringsLoader.getOrLoad() // loading localization from a remote file
val string = getMyString().localized(strings)
```

Note: `StringDesc` is a multiple-source container for Strings: in StringDesc we can use a resource,
plurals, formatted variants, or raw string. To convert `StringDesc` to `String` on Android
call `toString(context)` (a context is required for the resources usage), on iOS -
call `localized()`.

#### Compose Multiplatform

with compose you can just call in `commonMain`

```kotlin
val string: String = stringResource(MR.strings.my_string)
```

#### MR directly from native side

Android:

```kotlin
val string = MR.strings.my_string.desc().toString(context = this)
```

iOS:

```swift
let string = MR.strings().my_string.desc().localized()
```

#### Get resourceId for Jetpack Compose / SwiftUI

Android:

```kotlin
val resId = MR.strings.my_string.resourceId
```

for example in Compose:

```kotlin
text = stringResource(id = MR.strings.email.resourceId)
```

iOS SwiftUI:

```swift
let resource = MR.strings().email
Text(
    LocalizedStringKey(resource.resourceId),
    bundle: resource.bundle
)
```

Note: more info in issue [#126](https://github.com/icerockdev/moko-resources/issues/126).

### Example 2 - formatted localization string

In `commonMain/moko-resources/base/strings.xml` add:

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
    <string name="my_string_formatted">My format \'%s\'</string>
</resources>
```

Then add the localized values for other languages like in example #1.
Now create the following function in `commonMain`:

```kotlin
fun getMyFormatDesc(input: String): StringDesc {
    return StringDesc.ResourceFormatted(MR.strings.my_string_formatted, input)
}
```

To create formatted strings from resources you can also use extension `format`:

```kotlin
fun getMyFormatDesc(input: String): StringDesc {
    return MR.strings.my_string_formatted.format(input)
}
```

Now add support on the platform side like in example #1:
Android:

```kotlin
val string = getMyFormatDesc("hello").toString(context = this)
```

iOS:

```swift
let string = getMyFormatDesc(input: "hello").localized()
```

Warning: Do no mix positioned placeholders with unpositioned ones within a string, as this may lead
to
different behaviour on different platforms. Stick to one style for each string.

### Example 3 - plural string

The first step is to create a file `plurals.xml` in `commonMain/moko-resources/base` with the
following content:

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
    <plural name="my_plural">
        <item quantity="zero">zero</item>
        <item quantity="one">one</item>
        <item quantity="two">two</item>
        <item quantity="few">few</item>
        <item quantity="many">many</item>
        <item quantity="other">other</item>
    </plural>
</resources>
```

Then add the localized values for other languages like in example #1.
Next, create a function in `commonMain`:

```kotlin
fun getMyPluralDesc(quantity: Int): StringDesc {
    return StringDesc.Plural(MR.plurals.my_plural, quantity)
}
```

Now add support on the platform side like in example #1:
Android:

```kotlin
val string = getMyPluralDesc(10).toString(context = this)
```

iOS:

```swift
let string = getMyPluralDesc(quantity: 10).localized()
```

### Example 4 - plural formatted string

The first step is to create file `plurals.xml` in `commonMain/moko-resources/base` with the following
content:

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
    <plural name="my_plural">
        <item quantity="zero">no items</item>
        <item quantity="one">%d item</item>
        <item quantity="two">%d items</item>
        <item quantity="few">%d items</item>
        <item quantity="many">%d items</item>
        <item quantity="other">%d items</item>
    </plural>
</resources>
```

Then add the localized values for other languages like in example #1.
Next, create a function in `commonMain`:

```kotlin
fun getMyPluralFormattedDesc(quantity: Int): StringDesc {
    // we pass quantity as selector for correct plural string and for pass quantity as argument for formatting
    return StringDesc.PluralFormatted(MR.plurals.my_plural, quantity, quantity)
}
```

To create formatted plural strings from resources you can also use extension `format`:

```kotlin
fun getMyPluralFormattedDesc(quantity: Int): StringDesc {
    // we pass quantity as selector for correct plural string and for pass quantity as argument for formatting
    return MR.plurals.my_plural.format(quantity, quantity)
}
```

And like in example #1, add the platform-side support:
Android:

```kotlin
val string = getMyPluralFormattedDesc(10).toString(context = this)
```

iOS:

```swift
let string = getMyPluralFormattedDesc(quantity: 10).localized()
```

Compose:

With compose, you can simply use `pluralStringResource`

```kotlin
Text(
    text = pluralStringResource(
        MR.plurals.runtime_format,
        quantity,
        quantity
    )
)
```

### Example 5 - pass raw string or resource

If we already use some resources as a placeholder value, we can use `StringDesc` to change the
string source:

```kotlin
fun getUserName(user: User?): StringDesc {
    if (user != null) {
        return StringDesc.Raw(user.name)
    } else {
        return StringDesc.Resource(MR.strings.name_placeholder)
    }
}
```

And just like in example 1 usage on platform side:
Android:

```kotlin
val string1 = getUserName(user).toString(context = this) // we got name from User model
val string2 = getUserName(null).toString(context = this) // we got name_placeholder from resources
```

iOS:

```swift
let string1 = getUserName(user: user).localized() // we got name from User model
let string2 = getUserName(user: null).localized() // we got name_placeholder from resources
```

### Example 6 - Select localization in runtime

You can force `StringDesc` to use preferred localization in common code:

```kotlin
StringDesc.localeType = StringDesc.LocaleType.Custom("es")
```

and return to system behaviour (when localization depends on device settings):

```kotlin
StringDesc.localeType = StringDesc.LocaleType.System
```

Android:

Add this to your app's `build.gradle` to keep all locales in resulting [App Bundle](https://www.youtube.com/watch?v=IPLhLu0kvYw&ab_channel=AndroidDevelopers) if you want them all to be available in runtime (Otherwise, when the user downloads the app from PlayMarket, resources for his system locale only will be available).

```
android {
    bundle {
        language {
            enableSplit = false
        }
    }
}
```

### Example 7 - Shared Images

Place images in the `commonMain/moko-resources/images` directory. Nested directories are also supported.

#### png and jpg

Image names should end with one of:

- `@0.75x` - android ldpi;
- `@1x` - android mdpi, ios 1x;
- `@1.5x` - android hdpi;
- `@2x` - android xhdpi, ios 2x;
- `@3x` - android xxhdpi, ios 3x;
- `@4x` - android xxxhdpi.

If we add the following files to `commonMain/moko-resources/images`:

- `home_black_18@1x.png`
- `home_black_18@2x.png`

Then we get an autogenerated `MR.images.home_black_18` `ImageResource` in code. Usage:

- Android: `imageView.setImageResource(image.drawableResId)`
- iOS: `imageView.image = image.toUIImage()`

#### dark mode

To support Dark Mode images, you can add -dark and optionally -light to the name of an image. Make sure the rest of the name matches the corresponding light mode image:

- `car.svg`
- `car-dark.svg`

#### svg

The Image generator also supports `svg` files.

If we add the following file to `commonMain/moko-resources/images`:

- `car_black.svg`

Then we get an autogenerated `MR.images.car_black` `ImageResource` in code. Usage:

- Android: `imageView.setImageResource(image.drawableResId)`
- iOS: `imageView.image = image.toUIImage()`

On Android it is a `VectorDrawable`,

On iOS iOS 13 or later it is a `UIImage` in the Assets catalog with `preserves-vector-representation` set to `true`.

#### images by name

You can get images by their name, too.

In `commonMain` create a `Resources.kt` file with the content below.

```kotlin
fun getImageByFileName(name: String): ImageResource {
    val fallbackImage = MR.images.transparent
    return MR.images.getImageByFileName(name) ?: fallbackImage
}
```

Usage:

- Android: `imageView.setImageResource(getImageByFileName("image_name"))`
- iOS: `imageView.image = ResourcesKt.getImageByFileName(name: "image_name").toUIImage()!`

#### Compose Multiplatform

With compose, you can simply use a `painterResource` in `commonMain`

```kotlin
val painter: Painter = painterResource(MR.images.home_black_18)
```

#### SwiftUI

For SwiftUI, create this `Image` extension:

```swift
extension Image {
    init(resource: KeyPath<MR.images, ImageResource>) {
        self.init(uiImage: MR.images()[keyPath: resource].toUIImage()!)
    }
}
```

Then, you can refer to `ImageResource`s directly by their key path, which provides compiler errors for typos or missing resources:

```swift
Image(resource: \.home_black_18)
```

### Example 8 - pass font

Fonts resources directory is `commonMain/moko-resources/fonts`.
Supported type of resources:
- `ttf`
- `otf`

If we add to `commonMain/moko-resources/fonts` files:
- `Raleway-Bold.ttf`
- `Raleway-Regular.otf`
- `Raleway-Italic.ttf`

We got autogenerated:
- `MR.fonts.raleway_italic`,
- `MR.fonts.raleway_regular`,
- `MR.fonts.raleway_bold_italic`

in code, that we can use:

- Android: `textView.typeface = font.getTypeface(context = this)`
- iOS: `textView.font = font.uiFont(withSize: 14.0)`

#### Compose Multiplatform

with compose you can just call in `commonMain`

```kotlin
val fontFamily: FontFamily = fontFamilyResource(MR.fonts.Raleway.italic)
```

or you can get `Font`

```kotlin
val font: Font = MR.fonts.Raleway.italic.asFont(
  weight = FontWeight.Normal, // optional
  style = FontStyle.Normal // optional
)
```

### Example 9 - pass colors

Colors resources directory is `commonMain/moko-resources/colors`.
Colors files is `xml` with format:

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- format: #RRGGBB[AA] or 0xRRGGBB[AA] or RRGGBB[AA] where [AA] - optional -->
    <color name="valueColor">#B02743FF</color>
    <color name="referenceColor">@color/valueColor</color>
    <color name="themedColor">
        <light>0xB92743FF</light>
        <dark>7CCFEEFF</dark>
    </color>
    <color name="themedReferenceColor">
        <light>@color/valueColor</light>
        <dark>@color/referenceColor</dark>
    </color>
</resources>
```

If you want use one color without light/dark theme selection:

```xml

<color name="valueColor">#B02743FF</color>
```

If you want use value of other color - use references:

```xml

<color name="referenceColor">@color/valueColor</color>
```

If you want different colors in light/dark themes:

```xml

<color name="themedColor">
    <light>0xB92743FF</light>
    <dark>7CCFEEFF</dark>
</color>
```

Also themed colors can be referenced too:

```xml

<color name="themedReferenceColor">
    <light>@color/valueColor</light>
    <dark>@color/referenceColor</dark>
</color>
```

Colors available in common code insode `MR.colors.**` as `ColorResource`.
`ColorResource` can be read from platform side:

android:

```kotlin
val color: Int = MR.colors.valueColor.getColor(context = this)
```

iOS:

```swift
val color: UIColor = MR.colors.valueColor.getUIColor()
```

macOS:

```swift
val color: NSColor = MR.colors.valueColor.getNSColor()
```

jvm:

```kotlin
val light: Color = MR.colors.valueColor.lightColor
val dark: Color = MR.colors.valueColor.darkColor
```

web:

```kotlin
val light: Color = MR.colors.valueColor.lightColor
val dark: Color = MR.colors.valueColor.darkColor
```

#### Compose Multiplatform

with compose you can just call in `commonMain`

```kotlin
val color: Color = colorResource(MR.colors.valueColor)
```

### Example 10 - plain file resource access

The first step is a create a resource file `test.txt` for example,
in `commonMain/moko-resources/files`
After gradle sync we can get file by id `MR.files.test`
Moko-resources has out of box implementation function for read text files from common
code - `readText()`

Usage on Android:

```
val text = MR.files.test.getText(context = this)
```

Usage on Apple:

```
val text = MR.files.test.readText()
```

If you want to read files not as text, add your own implementation to expect/actual FileResource

#### Compose Multiplatform

with compose you can just call in `commonMain`

```kotlin
val fileContent: String? by MR.files.test.readTextAsState()
```

### Example 11 - assets access

Assets allow you save directories hierarchy (in files structure is plain). Locate files
to `commonMain/moko-resources/assets` and access to it by `MR.assets.*`

#### Compose Multiplatform

with compose you can just call in `commonMain`

```kotlin
val assetContent: String? by MR.assets.test.readTextAsState()
```

## Known issues

### iOS shows key instead of localized text

1. check that generated `Localizable.strings` file is valid - open it by Xcode (located in `shared/shared/build/bin/iosSimulatorArm64/debugFramework/shared.framework/<project-name>:shared.bundle/Contents/Resources/Base.lproj/Localizable.strings` and in other `.lproj` directories. If Xcode show error in file - you should fix content of strings.xml (for example you use some special character that broke file).

2. check that your generated `.bundle` exist inside application at runtime. In Xcode inside group `Products` select your application and click `Show in Finder`. Then click `Show Package Contents`. Inside `.app` you should see `.bundle` in root directory if you use static framework. And in `Frameworks/shared.framework` if you use dynamic framework. If `bundle` missed - check installation guide. Specifically xcode build phase part if you use static framework. And check that you apply moko-resources plugin in `shared` gradle module.

3. check that your `strings.xml` contains all keys for language that you use. If you have keys `test1`, `test2` in `Base/strings.xml`, and only `test1` in `ru/strings.xml` then you got key instead of text in ru locale for `test2` key. iOS not fallback to base locale now

## Samples

In `samples` directory you can find multiple projects showed different usages.

- [resources-gallery](samples/resources-gallery) - android, iOS, macOS, jvm, web applications with
  all resources types usage.
- [compose-resources-gallery](samples/compose-resources-gallery) - android, iOS, jvm, web
  Compose Multiplatform applications with all resources types usage.
- [android-mpp-app](samples/android-mpp-app) - android application that configured as multiplatform
  module.
- [auto-manifest](samples/auto-manifest) - sample of
  usage [auto-manifest](https://github.com/GradleUp/auto-manifest) plugin.
- [compose-jvm-app](samples/compose-jvm-app) - Compose Desktop jvm application with resources usage.
- [ios-static-xcframework](samples/ios-static-xcframework) - iOS application with static XCFramework
  and resources.
- [kotlin-ios-app](samples/kotlin-ios-app) - iOS application without swift - full code on kotlin,
  with resources usage.

## Set Up Locally

In root of repository contains `moko-resources` gradle project - libraries and gradle plugin. You
can just open project in IDE and develop. Then for tests in samples you should run
run `./gradlew publishToMavenLocal` gradle task. After this you can open any sample from `samples`
in IDE and test your local version of `moko-resources`.

To check your changes before pull request run:
```bash
# check lib & plugin
./local-check.sh
# check samples
./local-samples-check.sh
```

## Contributing

All development (both new features and bug fixes) is performed in the `develop` branch. This
way `master` always contains the sources of the most recently released version. Please send PRs with
bug fixes to the `develop` branch. Documentation fixes in the markdown files are an exception to
this rule. They are updated directly in `master`.

The `develop` branch is pushed to `master` on release.

For more details on contributing please see the [contributing guide](CONTRIBUTING.md).

## License

    Copyright 2019 IceRock MAG Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

[badge-android]: http://img.shields.io/badge/platform-android-6EDB8D.svg?style=flat

[badge-ios]: http://img.shields.io/badge/platform-ios-CDCDCD.svg?style=flat

[badge-js]: http://img.shields.io/badge/platform-js-F8DB5D.svg?style=flat

[badge-jvm]: http://img.shields.io/badge/platform-jvm-DB413D.svg?style=flat

[badge-linux]: http://img.shields.io/badge/platform-linux-2D3F6C.svg?style=flat

[badge-windows]: http://img.shields.io/badge/platform-windows-4D76CD.svg?style=flat

[badge-mac]: http://img.shields.io/badge/platform-macos-111111.svg?style=flat

[badge-watchos]: http://img.shields.io/badge/platform-watchos-C0C0C0.svg?style=flat

[badge-tvos]: http://img.shields.io/badge/platform-tvos-808080.svg?style=flat

[badge-wasm]: https://img.shields.io/badge/platform-wasm-624FE8.svg?style=flat

[badge-nodejs]: https://img.shields.io/badge/platform-nodejs-68a063.svg?style=flat

[badge-iosX64]: https://img.shields.io/badge/platform-iosX64-CDCDCD?style=flat

[badge-iosArm64]: https://img.shields.io/badge/platform-iosArm64-CDCDCD?style=flat

[badge-iosSimulatorArm64]: https://img.shields.io/badge/platform-iosSimulatorArm64-CDCDCD?style=flat

[badge-macosX64]: https://img.shields.io/badge/platform-macosX64-111111?style=flat

[badge-macosArm64]: https://img.shields.io/badge/platform-macosArm64-111111?style=flat


[Česká verze](README.cs.md) / [Deutsche Version](README.de.md) / [English version](README.en.md) / Polska wersja / [Slovenská verzia](README.sk.md)

# Wulkanowy

[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions)
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
[![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/)
[![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases)
[![Crowdin](https://badges.crowdin.net/wulkanowy2/localized.svg)](https://translate.wulkanowy.net.pl)

Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica

## Funkcje

* logowanie za pomocą e-maila i hasła
* funkcje ze strony internetowej dziennika:
    * oceny
    * statystyki ocen
    * frekwencja
    * procent frekwencji
    * sprawdziany
    * plan lekcji
    * lekcje zrealizowane
    * wiadomości
    * zadania domowe
    * uwagi
    * szczęśliwy numerek
    * dodatkowe lekcje
    * zebrania w szkole
    * informacje o uczniu i szkole
* obliczanie średniej niezależnie od preferencji szkoły
* powiadomienia np. o nowej ocenie
* obsługa wielu kont wraz z możliwością zmiany nazwy ucznia
* ciemny i czarny (AMOLED) motyw
* tryb offline
* opcjonalne reklamy umożliwiające wsparcie projektu

## Pobierz

Aktualną wersję możesz pobrać ze sklepu Google Play, F-Droid lub Huawei AppGallery

[](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
[](https://f-droid.org/packages/io.github.wulkanowy/)
[](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)

Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#download), która zawiera nowe funkcje przygotowywane do następnego wydania

## Zbudowana za pomocą

* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)
* [Hilt](https://dagger.dev/hilt/)
* [Room](https://developer.android.com/topic/libraries/architecture/room)
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)

## Współpraca

Wnieś swój wkład w projekt, tworząc PR lub wysyłając issue na GitHub.

Dla osób zainteresowanych tłumaczeniem aplikacji na różne języki udostępniamy Crowdina
https://crowdin.com/project/wulkanowy2

## Licencja

Ten projekt udostępniany jest na licencji Apache License 2.0 - szczegóły w pliku [LICENSE](LICENSE)


## Rethink DNS + Firewall + VPN for Android
A [WireGuard](https://github.com/wireguard/wireguard-go) client, an [OpenSnitch](https://github.com/evilsocket/opensnitch)-inspired firewall and network monitor + a [pi-hole](https://github.com/pi-hole/pi-hole)-inspired DNS over HTTPS client with blocklists.

[](https://f-droid.org/packages/com.celzero.bravedns/)
[](https://play.google.com/store/apps/details?id=com.celzero.bravedns)

In other words, Rethink DNS + Firewall has three primary modes, VPN, DNS, and Firewall. The VPN (proxifier) mode supports multiple WireGuard upstreams in a split-tunnel configuration. The DNS mode routes all DNS traffic generated by apps to _any_ user chosen DNS-over-HTTPS or DNSCrypt resolver. The Firewall mode lets the user deny internet-access to entire applications based on events like screen-on / screen-off, app-foreground / app-background, unmetered-connection / metered-connection; or based on play-store defined categories like Social, Games, Utility, Productivity; or additionally, based on user-defined denylists.

![2](https://github.com/celzero/rethink-app/assets/56958445/618bb47c-586c-41b9-ba1c-f62c2bbc9649)
![3](https://github.com/celzero/rethink-app/assets/56958445/c74f3485-7197-4e5b-860f-c2b11c556cee)
![4](https://github.com/celzero/rethink-app/assets/56958445/a2032d44-f07c-45e9-801b-7abe0cac0ead)
![5](https://github.com/celzero/rethink-app/assets/56958445/b9973e69-d45e-4be9-bd42-b80fb2768ec5)
![6](https://github.com/celzero/rethink-app/assets/56958445/27a45c02-7046-41b1-89bb-7fe3624ed717)
![7](https://github.com/celzero/rethink-app/assets/56958445/7246da25-6541-405e-b2a4-444dbb5c60f4)

### VPN / Proxifier
Rethink supports forwarding TCP and UDP connections over SOCKS5, HTTP CONNECT, and WireGuard tunnels. Split-tunneling further helps run multiple such tunnels at the same time and lets users route different apps over different tunnels. For example, one could route Firefox over SOCKS5 connecting to Tor, Netflix over WireGuard connecting through any popular VPN provider, and Telegram or WhatsApp over censorship-resistant HTTP CONNECT endpoints at the same time.

### Firewall
The firewall doesn't really care about the connections per se rather what's making those connections. This is different from the traditional firewalls but in-line with [Little Snitch](https://www.obdev.at/products/littlesnitch/index.html), [LuLu](https://objective-see.com/products/lulu.html), [Glasswire](https://glasswire.com/) and others.

Currently, per-app connection mapping is implemented by capturing `udp` and `tcp` connections managed by [`firestack`](https://github.com/celzero/firestack) (written in golang) and asking [ConnectivityService for the owner](https://developer.android.com/about/versions/10/privacy/changes#proc-net-filesystem), an API available only on Android 10 or higher. `procfs` (`/proc/net/tcp` and `/proc/net/udp`) is read on-demand to track per-app connections like [NetGuard](https://github.com/M66B/NetGuard/) or OpenSnitch do, on Android 9 and lower versions.

### Network Monitor
A network monitor is a per-app report-card of sorts on when connections were made, how many were made, and to where. Tracking TCP has turned out to be so far straight-forward. DNS packets are trickier to track, and so a rough heuristic is used for now, which may not hold good in all cases.

### DNS over HTTPS client
Almost all of the network related code (`firestack`), including DNS over HTTPS split-tunnel, is a hard fork of [Jigsaw-Code/outline-go-tun2socks](https://github.com/Jigsaw-Code/outline-go-tun2socks) written in golang. The UI is vastly different but borrows minimally from [Jigsaw-Code/Intra](https://github.com/Jigsaw-Code/Intra/). A split-tunnel traps requests sent to the VPN's DNS endpoint and relays it to a DNS-over-HTTPS / DNSCrypt endpoint of the user's choosing, logging the end-to-end latency, time of request, the dns request query itself and its answer.

### The Rethink DNS Resolver
A malware and ad-blocking DNS over HTTPS resolver at `https://sky.rethinkdns.com/1:IAAgAA==` (deployed to 300+ locations world-wide via Cloudflare Workers) is the default DNS endpoint on the app, though the user is free to change that. A configurable DNS resolver that lets users add or remove denylists and allowlists, add rewrites, analyse DNS requests is launching late 2023. Right now, a free-to-use DNS over HTTPS endpoint with custom blocklists can be setup here: [rethinkdns.com/configure](https://rethinkdns.com/configure).

The resolver is deployed to [Fly.io](https://fly.io/) at `max.rethinkdns.com` and [Deno Deploy](https://deno.com/deploy) at `rdns.deno.dev` too, apart from the default deployment on [Cloudflare Workers](https://workers.dev).

The resolver is open source software: [serverless-dns](https://github.com/serverless-dns/serverless-dns).

### The Rethink Proxy Network
Routing TCP connections over a serverless proxy (hosted on Cloudflare Workers) [will soon be part of Rethink](https://github.com/celzero/rethink-app/issues/946). Users would be able to self-host these
or use the ones run by us for $1 month of unlimited bandwidth. This service is expected to be launching late 2023.

The proxy is open source software: [serverless-proxy](https://github.com/serverless-proxy/serverless-proxy).

### Community
[](https://github.com/sponsors/serverless-dns)
- The telegram community is super active and full of crypto-bros. Kidding. We are generally a welcoming bunch. Feel free to get in touch: [t.me/rethinkdns](https://t.me/rethinkdns).
- Or, if you prefer [Matrix](https://matrix.to/#/!jrTSpJiEkFNNBMhSaE:matrix.org) (which is bridged to Telegram).
- Or, email us: [hello@celzero.com](mailto:hello@celzero.com) (we read all emails immediately and reply once we fix the issues being reported).
- We regularly hangout in our subreddit: [r/rethinkdns](https://reddit.com/r/rethinkdns).
- We're also kind of active on the bird app, mostly nerd-sniping other engs or shit-posting about our tech stack: [twitter/rethinkdns](https://twitter.com/rethinkdns).

### Translation
Help translate Rethink DNS + Firewall on [Weblate](https://weblate.org/):

[![](https://hosted.weblate.org/widgets/rethink-dns-firewall/-/287x66-black.png)](https://hosted.weblate.org/engage/rethink-dns-firewall)

### What Rethink DNS + Firewall is not
Rethink is not an anonymity tool: It helps users tackle unabated censorship and surveillance but doesn't lay claim to protecting a user's identity at all times, if ever.

Rethink doesn't aim to be a feature-rich traditional firewall: It is more in-line with [Little Snitch](https://www.obdev.at/products/littlesnitch/index.html) than IP tables, say.

Rethink is not an anti-virus: Rethink may stop users from phishing attacks, malware, scareware websites through its DNS-based blocklists, but it doesn't actively mitigate threats or even look for them or act on them, otherwise.

### What Rethink DNS + Firewall aspires to be
To turn Android devices into user-agents: Something that users can control as they please without requiring root-access. A big part of this, for an always-on, always-connected devices, is capturing network traffic and reporting it in a way that makes sense to the end-users who can then take a series of actions to limit their exposure but not necessarily eliminate it. Take DNS for example-- for most if not all connections, apps send out a DNS request first, and by tracking just those one can glean a lot of intelligence about what's happening with the phone and which app's responsible.

To deliver the promise of open-internet for all: With the inevitable ESNI standardization and the imminent adoption of DNS over HTTPS and DNS over TLS across operating systems, we're that much closer to an open internet. Of course, *Deep Packet Inspection* remains a credible threat that can't be mitigated with this, but it is one example of delivering maximum impact (circumvent internet censorship in most countries) with minimal effort (not requiring use of a VPN or access via IPFS, for example). Rethink would continue to make these technologies accessible in the most simplest way possible, especially the ones that get 90% of the way there with 10% effort.

## Development
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/celzero/rethink-app/badge)](https://securityscorecards.dev/viewer/?uri=github.com/celzero/rethink-app)

1. Feel free to fork and send along a pull request for any reproducible bug fixes.
  1. The codebase is raw and is lacking documentation and comprehensive tests. If you need help, feel free to create a Wikipage to highlight the pain with building, testing, writing, committing code.
  2. Write descriptive commit messages that explain concisely the changes made.
  3. Each commit must reference an open issue on the project. This is to make sure there isn't duplicated effort more than anything else.
2. If you plan to work on a feature, please create a github issue on the project first to kickstart the discussion before committing to doing any work. Again, this is to avoid duplicate work more than anything else.
3. Prod releases are usually once every 2 months, while betas are released bi-weekly.

## Tenets (unless you know better ones)
We aren't there yet, may never will be but these are some tenets for the project for the foreseeable future.

- Make it right, make it secure, make it resilient, make it fast. In that order.
- Easy to use, no-root, no-gimmicks features that are anti-censorship and anti-surveillance.
  - Easy to use: Any of the 3B+ Android users must be able to use it. Think CleanMaster / Instagram levels of ease-of-use.
  - no-root: Shouldn't require root-access for any functionality added to it.
  - no-gimmicks: Misleading material bordering on scareware, for example.
  - anti-censorship: Features focused on helping bring an open internet to everyone, preferably in the most efficient way possible (both monetarily and technically).
 - Anti-surveillance: As above, but features that further limit (may not necessarily eliminate) surveillance by apps.
- Incremental changes in balance with newer features.
  - For example, work on nagging UI issues or OEM specific bugs, must be taken up on equal weight to newer features, and a release must probably establish a good balance between the two. However; working on only incremental changes for a release is fine.
- Opinionated. Chip-away complexity. Do not expect users to require a PhD in Computer Science to use the app.
  - No duplicate functionality.
  - A concerted effort to not provide too many tunable knobs and settings. To err on the side of easy over simple.
- Ignore all tenets.
  - Common sense always takes over when tenets get in the way.
- Must be distributable on the PlayStore, at least some toned down version of it.
  - This unfortunately means on-device blocklists aren't possible; however, [Cloudflare Gateway](https://www.cloudflare.com/teams-gateway/)-esque cloud-based per-user blocklists get us the same functionality.
- Practice what you preach: Be obsessively private and secure.

## Backstory
[](https://fossunited.org/grants)
[](https://osomprivacy.com/)
[](https://builders.mozilla.community/old/alumni.html)

Internet censorship (sometimes ISP-enforced and often times government-enforced), unabated dragnet surveillance (by pretty much every company and app) stirred us upon this path. The three of us university classmates, [Mohammed](https://www.linkedin.com/in/hussain-mohammed-2525a626/), [Murtaza](https://www.linkedin.com/in/murtaza-aliakbar/), [Santhosh](https://www.linkedin.com/in/santhosh-ponnusamy-2b781244/) got together in late 2019 in the sleepy town of Coimbatore, India to do something about it. Our main gripe was there were all these wonderful tools that people could use but couldn't, either due to cost or due to inability to grok Computer-specific jargon. A lot has happened since we started and a lot has changed but our focus has always been on Android and its 2B+ unsuspecting users. The current idea has been in the works for since May 2020, with the pandemic derailing a bit of progress, and a bit of snafu with abandoning our previous version in favour of the current fork, which we aren't proud of yet, but it is a start. All's good now that we've won a grant from the [Mozilla Builders MVP program](https://builders.mozilla.community/) to go ahead and build this thing that we wanted to... do so faster... and not simply sleep our way through the execution. I hope you're excited but not as much as us that you quit your jobs for this like we did.


This is a bare-bones Android Studio project implementing baresip based SIP User Agent for Android. Its development is motivated by need for a secure, privacy focused SIP user agent for Android that does not depend on third party push notification services.

Currently the application supports voice calling and messaging, UDP, TCP, TLS, and WSS signaling transports, voicemail Message Waiting Indication, call transfers (REFER), PCMU/PCMA, Codec2, G.722, G.722.1, G.726, G.729, AMR, and Opus voice codecs, as well as ZRTP and (DTLS) SRTP media encapsulation.

If you need video calling and have a device with Android version 7.0 or newer that supports Camera2 API at LEVEL3, you can instead of this application install its sister application baresip+ from video branch.

After cloning the project, generate static libraries and include files to distribution directory using master branch of libbaresip-android.

Then in Android Studio (tested with Android Studio Jellyfish | 2023.3.1):

- Open an existing Android Studio project

- File -> Invalidate Caches ... -> Invalidate & Restart

- Build -> Generate Signed Bundle / APK ...

Ready to be installed baresip app is available from F-Droid and from GitHub.  Signing certificate SHA-256 fingerprint of the GitHub APKs is FE:CC:79:C2:0A:B7:25:B9:B7:8B:B1:6A:75:BA:9A:04:09:28:22:CF:52:BA:32:E4:A4:37:17:0A:68:02:06:02.  Use `keytool -printcert -jarfile app-release.apk` to verify.

Language translations are managed via baresip Weblate project.

Copyright (c) 2018 TutPro Inc. Distributed under BSD-3-Clause license.


[![official JetBrains project](http://jb.gg/badges/official-flat-square.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![JetBrains plugins][plugin-version-svg]][plugin-repo]
[![JetBrains plugins][plugin-downloads-svg]][plugin-repo]
[![JetBrains plugins][plugin-rating-svg]][plugin-repo]

## The JetBrains Academy plugin

Learn and teach programming languages such as
[Kotlin](https://kotlinlang.org/),
[Java](https://www.java.com),
[Python](https://www.python.org/),
[JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript),
[Rust](https://www.rust-lang.org/),
[Scala](https://www.scala-lang.org/),
[C++](https://isocpp.org/),
[Go](https://golang.org/), and
[PHP](https://www.php.net/), through interactive courses right in your JetBrains IDE.

**As a learner**, you can study programming while gaining experience with professional development tools.
Join a step-by-step course, work on real-world projects, complete missions, participate in contests, or try them all.
Read the [learner start guide](https://plugins.jetbrains.com/plugin/10081-jetbrains-academy/docs/learner-start-guide.html) for more information.

**As an educator**, you can create your own courses and share them with others either privately or publicly.
Combine theoretical learning and hands-on practice, test user knowledge with different sets of tasks, and provide extra assistance with feedback and hints.
Read the [course creator start guide](https://plugins.jetbrains.com/plugin/10081-jetbrains-academy/docs/educator-start-guide.html) for more information.

The best way to learn what this plugin is about is to check out the JetBrains Academy
[documentation](https://plugins.jetbrains.com/plugin/10081-jetbrains-academy/docs).

### Issue tracker
Please submit your issues to the JetBrains Academy tracker on [YouTrack](https://youtrack.jetbrains.com/issues/EDU).

### Resources
* This plugin comes with integration with [JetBrains Academy on Hyperskill](https://hi.hyperskill.org/how-we-teach), a hands-on platform for learning to program.
* You can read more about plugin development in [IntelliJ Platform SDK docs](http://www.jetbrains.org/intellij/sdk/docs/index.html).

[plugin-version-svg]: https://img.shields.io/jetbrains/plugin/v/10081-jetbrains-academy?style=flat-square
[plugin-downloads-svg]: https://img.shields.io/jetbrains/plugin/d/10081-jetbrains-academy?style=flat-square
[plugin-rating-svg]: https://img.shields.io/jetbrains/plugin/r/rating/10081-jetbrains-academy?style=flat-square
[plugin-repo]: https://plugins.jetbrains.com/plugin/10081-jetbrains-academy


[![Actions Status](https://img.shields.io/github/actions/workflow/status/F43nd1r/Acrarium/tests.yml?label=Tests&style=for-the-badge)](https://github.com/F43nd1r/Acrarium/actions)
[![License](https://img.shields.io/github/license/F43nd1r/Acrarium?style=for-the-badge)](https://github.com/F43nd1r/Acrarium/blob/master/LICENSE)
[![Docker Pulls](https://img.shields.io/docker/pulls/f43nd1r/acrarium?style=for-the-badge)](https://hub.docker.com/repository/docker/f43nd1r/acrarium)
[![Github Downloads](https://img.shields.io/github/downloads/F43nd1r/Acrarium/total?label=Github%20Downloads&style=for-the-badge)](https://github.com/F43nd1r/Acrarium/releases)
[![Latest Version](https://img.shields.io/docker/v/f43nd1r/acrarium?label=Latest%20version&style=for-the-badge)](https://github.com/F43nd1r/Acrarium/releases)

A Backend for [ACRA](https://github.com/ACRA/acra) written in Kotlin using Spring Boot, Vaadin and MySQL

# Setup

See [Wiki Setup guide](https://github.com/F43nd1r/acra-backend/wiki/Setup-guide)

# Screenshots

###### Listing reports

![report list](screenshots/reports.png)

###### Statistics

![statistics](screenshots/statistics.png)

###### Proguard and Export Support

![admin tab](screenshots/admin.png)

###### Report Summary and Attachment Support

![report summary](screenshots/summary.png)

###### Full Report content

![report content](screenshots/details.png)

###### Dark Theme

![dark theme](screenshots/dark.png)

# Development

## Running locally

```shell
./gradlew bootRun
```

## Building release

### Jar

```shell
./gradlew bootJar -x test -Pvaadin.productionMode=true
```

### Docker Image

```shell
./gradlew bootJar -x test -Pvaadin.productionMode=true
docker build -t f43nd1r/acrarium:git acrarium
```

# License

All source code in this repository is licensed under the Apache License 2.0 (see [LICENSE](LICENSE))

# Credits

Thanks to

- [Mirza Zulfan](https://github.com/mirzazulfan) for creating the logo.
- [aptly-io](https://github.com/aptly-io) (Dutch), [Federico Iosue](https://github.com/federicoiosue) (Italian), [Astarivi](https://github.com/astarivi) (
  Spanish), [iisimpler](https://github.com/iisimpler) (Chinese) for contributing to localization.


# Atom Material Icons Plugin for JetBrains

[![All Contributors](https://img.shields.io/badge/all_contributors-6-orange.svg?style=flat-square)](#contributors-)

  Atom Material Icons

This plugin is a port of the [Atom File Icons](https://github.com/file-icons/atom) for Atom and the icons of
the [Material Theme UI](https://github.com/mallowigi/material-theme-issues) plugin.

## VSCode Extension

<https://marketplace.visualstudio.com/items?itemName=AtomMaterial.a-file-icon-vscode&ssr=false#overview>

## Chrome Extension

<https://chrome.google.com/webstore/detail/atom-file-icons-web/pljfkbaipkidhmaljaaakibigbcmmpnc>

## Firefox Extension

<https://addons.mozilla.org/en-US/firefox/addon/atom-file-icons-web/>

- Replaces **file icons** with their relevant logo icons
  - According to their extension (Java, PHP, Ruby...)
  - According to the framework (Android, NPM, RSpec...)
  - According to the program used with (Babel, Docker, CircleCI...)
- Replaces **directories**:
  - With a common pattern: src, main, app, img, docs...
  - With a specific pattern: node_modules, .vscode, .git...
- Replaces the **PSI (Program Structure Interface)** icons:
  - Classes, Interfaces, Enums, Abstract...
  - Methods, Lambdas, Inherits, Overrides...
- Replaces the **UI Icons**:
  - Toolbar icons (actions)
  - Gutter icons (debugger)
  - Node icons (folders)...
- **Monochrome filter**: Set a monochrome filter to the whole UI
  - Ability to select the color
- **Arrows Style**: Customize the look of the arrows in Tree components
  - Material: Chevron-like arrows
  - Darcula: Regular triangle arrows
  - Plus-Minus: Plus and Minus signs
  - Arrows: Simple Arrows
  - None: No arrows
- **Hollow Folders**: Add custom decorations on folders containing opened files
- **Custom Icon Size**: Assign a custom icon size (between 12 and 24)
- **Accent Color**: Change the color of specific icons
  - Closing tab button
  - Highlighted arrows
  - Loading indicator...
- **Customizability**: Custom Settings
  - Settings Pages
  - Toolbar Action Buttons
- **Custom File and Directory associations** Customize your own associations
  - File associations by Regex
  - Folder associations
  - Preview default icons

## File Icons

![File Icons](https://raw.githubusercontent.com/mallowigi/iconGenerator/master/assets/files.png)

## Folder Icons

![Folder Icons](https://raw.githubusercontent.com/mallowigi/iconGenerator/master/assets/folders.png)

## Credits

Special credits to:

- [Atom File Icons](https://github.com/file-icons/atom)
  and [Sublime Text A File Icon](https://github.com/SublimeText/AFileIcon) for the idea
- [Scientifics Study Vectors](https://www.svgrepo.com/svg/121720/atom) for the plugin icon
- [File-Icons](https://github.com/file-icons/source/blob/master/charmap.md)
- [FontAwesome 4.7.0](https://fontawesome.com/v4.7.0/cheatsheet/)
- [MFixx](https://github.com/file-icons/MFixx/blob/master/charmap.md)
- [Devicons](https://github.com/file-icons/DevOpicons/blob/master/charmap.md)
- [Octicons](https://octicons.github.com/)
- [Material Design Icons](https://materialdesignicons.com/)
- [The Noun Project](https://thenounproject.com/)
- [Icongram](https://icongr.am/)

## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

Alex Simons
🚇 💻 🔌

Joris te Dorsthorst
🤔

Jack Chu
🐛

Donnie An
💻

Alexey Kunitsky
💻 🤔

Aparajita Fishman
🤔 💻

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification.
Contributions of any kind welcome!


# .NET Plugins for [<img src="https://cdn.worldvectorlogo.com/logos/teamcity.svg" height="20" align="center" alt="TeamCity" />](https://www.jetbrains.com/teamcity/)

[![official JetBrains project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Build](http://teamcity.jetbrains.com/app/rest/builds/buildType:(id:TeamCityPluginsByJetBrains_NetPlugin_NetDev)/statusIcon.svg)](http://teamcity.jetbrains.com/viewType.html?buildTypeId=TeamCityPluginsByJetBrains_NetPlugin_NetDev&guest=1)

# Plugins

* [.NET plugin](#net-plugin)
* [C# Script runner](#c-script-runner)
* [Inspections](#inspections)
* [Duplicates Finder](#duplicates-finder)

## .NET plugin

The TeamCity .NET plugin provides support for .NET tools in TeamCity. It simplifies building Windows and cross-platform applications that use .NET frameworks and libraries.

### Features

The plugin provides the following features:
* .NET build runner for [.NET CLI](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet), [MSBuild](https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild), [Visual Studio Test](https://docs.microsoft.com/en-us/visualstudio/test/vstest-console-options) and [Visual Studio Devenv](https://docs.microsoft.com/en-us/visualstudio/ide/reference/devenv-command-line-switches)
* [.NET SDK](https://docs.microsoft.com/en-us/dotnet/core/sdk) and .NET tools detection on TeamCity build agents
* Auto-discovery of build steps
* On-the-fly test reporting
* Supports code coverage tools
* Cleanup of NuGet caches to meet the agent [free space requirements](https://www.jetbrains.com/help/teamcity/?Free+disk+space)
* Supports [TeamCity Docker Wrapper](https://www.jetbrains.com/help/teamcity/docker-wrapper.html)

### Compatibility

The plugin is compatible with

- [TeamCity 2017.1+](https://www.jetbrains.com/teamcity/download/)
- [.NET CLI 1.0+](https://dotnet.microsoft.com/download/dotnet-core/)
- Visual Studio 2013+
- MSBuild 12+
- VSTest console 12+

### .NET CLI toolkit

To use the `dotnet` build runner, install [.NET CLI](https://dotnet.microsoft.com/download/dotnet-core/) and add the .NET CLI tools path to the `PATH` environment variable.

You can also configure the `DOTNET_HOME` environment variable for your TeamCity build agent user, for instance:

```
DOTNET_HOME=C:\Program Files\dotnet\
```

### Known issues

Tests might not be reported correctly for .NET Core xunit test projects when logging verbosity levels is `minimal` or `quiet` because of [issue](https://github.com/xunit/xunit/issues/1706).

## C# Script runner

### Features

* Allows executing a C# script on Windows, Linux, or macOS
* Cleanup of NuGet caches to meet the agent [free space requirements](https://www.jetbrains.com/help/teamcity/?Free+disk+space)
* Supports [TeamCity Docker Wrapper](https://www.jetbrains.com/help/teamcity/docker-wrapper.html)

### Compatibility

The plugin is compatible with

- [.NET runtime 3.1](https://dotnet.microsoft.com/download/dotnet/3.1)

## Inspections

The Inspections (ReSharper) build runner allows you to use the benefits of the [JetBrains ReSharper code quality analysis](https://www.jetbrains.com/help/resharper/Code_Analysis__Index.html) feature right in TeamCity, with the help of the bundled JetBrains ReSharper Command Line Tools. You can use the tools within TeamCity without any additional ReSharper license. ReSharper analyzes your C#, VB.NET, XAML, XML, ASP.NET, ASP.NET MVC, JavaScript, HTML, CSS code, and allows you to:

* Find probable bugs
* Eliminate errors and code smells
* Detect performance issues
* Improve the code structure and maintainability
* Ensure the code conforms to guidelines, standards and specifications

## Duplicates Finder

The Duplicates finder (ReSharper) build runner, based on [ReSharper Command Line Tools](https://www.jetbrains.com/resharper/features/command-line.html), is intended to catch similar code fragments and provide a report on the discovered repetitive blocks of C# and Visual Basic .NET code in Visual Studio 2003, 2005, 2008, 2010, 2012, 2013, and 2015 solutions.

## Additional Resources

* [TeamCity .NET](https://www.jetbrains.com/help/teamcity/net.html)
* [New approach and demo](https://blog.jetbrains.com/teamcity/2020/12/teamcity-integration-with-net-part-1-new-approach-and-demo/)
* [Testing and building projects](https://blog.jetbrains.com/teamcity/2020/12/teamcity-integration-with-net-part-2-testing-and-building-projects/)
* [Deploying projects](https://blog.jetbrains.com/teamcity/2020/12/teamcity-integration-with-net-part-3-deploying-projects/)

## Build

This project uses gradle as a build system. You can easily open it in [IntelliJ IDEA](https://www.jetbrains.com/idea/help/importing-project-from-gradle-model.html) or [Eclipse](http://gradle.org/eclipse/).

## Report and Track Issues

Please use our YouTrack to [report](https://youtrack.jetbrains.com/newIssue?project=TW&description=Expected%20behavior%20and%20actual%20behavior%3A%0A%0ASteps%20to%20reproduce%20the%20problem%3A%0A%0ASpecifications%20like%20the%20tool%20version%2C%20operating%20system%3A%0A%0AResult%20of%20'dotnet%20--info'%3A&c=Subsystem%20Agent%20-%20.NET&c=Assignee%20Nikolay.Pianikov&c=tag%20.NET%20Core) related issues.


# Trail Sense

> Use your Android phone's sensors to assist with wilderness treks or survival situations. Designed for entirely offline use.

[![](https://github.com/kylecorry31/Trail-Sense/workflows/Android%20CI/badge.svg)](https://github.com/kylecorry31/Trail-Sense/actions/workflows/android.yml)
[![](https://hosted.weblate.org/widgets/trail-sense/-/trail-sense-android/svg-badge.svg)](https://hosted.weblate.org/projects/trail-sense/trail-sense-android)
[![Nightly](https://github.com/kylecorry31/Trail-Sense/actions/workflows/nightly.yml/badge.svg)](https://github.com/kylecorry31/Trail-Sense/actions/workflows/nightly.yml)

Trail Sense is a tool, and just like any other tool that you bring into the wilderness, it's essential to have backup equipment and skills.

As featured in the [#WeArePlay](http://g.co/play/weareplay-usa) campaign!

See the [Technical Blog / Research](https://kylecorry.com/research/categories/trail-sense/)

        F-Droid
        Google Play

## Table of Contents

- [Feature Roadmap](#feature-roadmap)
- [Goals](#goals)
- [Features](#features)
- [Privacy](#privacy)
- [Contributing](#contributing)
- [FAQ](#faq)
- [Support](#support)
- [Open Source Credits](#open-source-credits)
- [License](#license)

## Feature Roadmap (2024)
The feature roadmap is a tentative outline of the major features that are planned to be completed in the next year. Smaller features may end up being implemented in between.
- [x] Augmented reality
- [ ] Customization
- [ ] Stability / performance
- [ ] Path navigation
- [ ] Experiment with the first plugin (Comms)

## Goals
- Trail Sense must not use the Internet in any way, as I want the entire app usable when there is no Internet connection
- Features must provide some benefits to people using the app while hiking, in a survival situation, etc.
- Features should make use of the sensors on a phone rather than relying on stored information such as guides
- Features must be based on peer-reviewed science or be verified against real world data
- [Use Cases](https://github.com/kylecorry31/Trail-Sense/wiki/Use-Cases)

## Features

- Designed for hiking, backpacking, camping, and geocaching
- Place beacons and navigate to them
- Follow paths
- Retrace your steps with backtrack
- Use a photo as a map
- Plan what to pack
- Be alerted before the sun sets
- Predict the weather
- Use your phone as a flashlight
- [And much more!](https://github.com/kylecorry31/Trail-Sense/wiki/Use-Cases)

See the need for a new feature? [Post it here!](https://github.com/kylecorry31/Trail-Sense/issues/1911)

For a list of community contributed device feature support, [go here](https://kylecorry.com/Trail-Sense/devices.html)

# Privacy

Location information gathered by this application does not leave your device (as a matter of fact, this app doesn't use the Internet at all). The altitude and pressure history for the last 48 hours is stored in local app storage - this is used to determine weather forecasts. The last known location is also stored in app preferences to allow faster load times and support app functionality when the GPS can not be reached. The beacons and paths store their location information in a local SQLite database. All of this information is cleared when you clear the app storage or delete it.

## Permissions
### Sensitive
- **POST_NOTIFICATIONS**
  - Allows Trail Sense to display notifications (backtrack, weather, sunset alerts, astronomy events, water boil timer, etc)
  - **When denied**: Alerts will not be displayed and some services may not function properly depending on your device manufacturer.
- **ACCESS_FINE_LOCATION / ACCESS_COARSE_LOCATION**
  - Allows Trail Sense to retrieve your location for navigation, weather (sea level calibration), and astronomy.
  - **When denied**: You will have the ability to mock your location under Settings > Sensors > GPS. On Android 14+, backtrack and weather will be unavailable due to Android OS constraints.
- **ACCESS_BACKGROUND_LOCATION**
  - Allows Trail Sense to retrieve your location for sunset alerts while in the background. On some devices, this will also improve the reliability of backtrack and weather monitor (though shouldn't be needed on most devices).
  - **When denied**: If you travel and do not open Trail Sense, but have Sunset Alerts enabled, the times will likely be inaccurate.
- **ACTIVITY_RECOGNITION**
  - Allows Trail Sense to use your phone's pedometer for distance calculation.
  - **When denied**: The pedometer will not work.
- **CAMERA**
  - Allows Trail Sense to use your camera on the sighting compass, clinometer, and for taking photos used by the Cloud Scanner, QR Code Scanner, and Photo Maps.
  - **When denied**: You will not be able to use the sighting compass, camera clinometer, or QR Code Scanner. You will need to pick an existing photo to use for the Cloud Scanner or Photo Maps.
- **SCHEDULE_EXACT_ALARM**
  - Allows Trail Sense to post a notification at an exact time. This is used by the Clock tool (when updating system time) and Sunset Alerts.
  - **When denied**: The clock and sunset alerts may not be accurate (can be off by several minutes).

### Not sensitive (always granted)
- **RECEIVE_BOOT_COMPLETED**
  - Allows Trail Sense to restart when you reboot your device. This will re-enable backtrack, weather monitor, and several other background services.
- **FOREGROUND_SERVICE**
  - Allows Trail Sense to start foreground services, such as backtrack and weather monitor.
- **FLASHLIGHT**
  - Allows Trail Sense to control the phone's flashlight.
- **VIBRATE**
  - Allows Trail Sense to vibrate the phone. Used for haptic feedback on dials and on the metal detector tool.
- **WAKE_LOCK**
  - Allows Trail Sense to reliably run services such as backtrack and weather monitor, especially when the frequency is under 15 minutes.

# Debug features
Only available on debug APKs / builds via Android Studio
- Weather tool's barometer chart shows unsmoothed readings in background
- Weather history, elevation history, path elevations, and latest cloud scan are logged to the files/debug folder in Trail Sense data as CSV files
- Weather settings shows statistics timing (for weather monitor service)
- Paths show statistics about timing (for backtrack service)

# Contributing

See the [CONTRIBUTING.md](https://github.com/kylecorry31/Trail-Sense/blob/main/CONTRIBUTING.md) file for details on contributing to Trail Sense.

# FAQ
The FAQ has moved [to the wiki](https://github.com/kylecorry31/Trail-Sense/wiki/Frequently-Asked-Questions-(FAQ))

# Support

The best way to support Trail Sense is to send me your feedback, share how you are using it, test nightly builds, or post your ideas for new features.

# Open Source Credits

- Thank you to everyone who tried out this app and opened issues, suggested features, provided translations, or tested debug builds for me
- Please see the in app licenses for all open source licenses
- Contributors and translators: https://github.com/kylecorry31/Trail-Sense/graphs/contributors
- [showdownjs](https://github.com/showdownjs/showdown): used for website markdown rendering [License](https://github.com/showdownjs/showdown/blob/master/LICENSE)

# License

[![License](https://img.shields.io/:license-mit-blue.svg?style=flat-square)](https://badges.mit-license.org)

- **[MIT license](LICENSE)**


# BitcoinKit

`bitcoin-kit-android` is a Bitcoin wallet toolkit implemented in Kotlin. It consists of following libraries:

- `bitcoincore` is a core library that implements a full Simplified Payment Verification (`SPV`) client in `Kotlin`. It implements Bitcoin `P2P Protocol` and can be extended to be a client of other Bitcoin forks like BitcoinCash, Litecoin, etc.
- `bitcoinkit` extends **bitcoincore**, makes it usable with `Bitcoin` network.
- `bitcoincashkit` extends **bitcoincore**, makes it usable with `BitcoinCash(ABC)` network.
- `litecoinkit` extends **bitcoincore**, makes it usable with `Litecoin` network.
- `dashkit` extends **bitcoincore**, makes it usable with `Dash` network.
- `hodler` is a plugin for `bitcoincore`, that makes it possible to lock certain amount of coins until some time in the future.

Being an SPV client, **bitcoincore** downloads and validates all the block headers, inclusion of transactions in the blocks, integrity and immutability of transactions as described in the Bitcoin whitepaper or delegates validation to the extensions that implement the forks of Bitcoin.

## Core Features

- [x] Bitcoin P2P Protocol implementation in Kotlin.
- [x] Full SPV implementation for fast mobile performance with account security and privacy in mind
- [x] `P2PK`, `P2PKH`, `P2SH-P2WPKH`, `P2WPKH` outputs support.
- [x] Restoring with mnemonic seed. (Generated from private seed phrase)
- [x] Restoring with [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) extended public key. (This becomes a `Watch account` unable to spend funds)
- [x] Quick initial restore over node API. (optional)
- [x] Handling transaction (Replacement)/(Double spend)/(Failure by expiration)
- [x] Optimized UTXO selection when spending coins.
- [x] [BIP69](https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki) or simple shuffle output ordering. (configurable)
- [x] [BIP21](https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki) URI schemes with payment address, amount, label and other parameters

# bitcoinkit

## Usage

### Initialization

First, you need an instance of *BitcoinKit* class. You can initialize it with Mnemonic seed or BIP32 extended key (private or public). To generate seed from mnemonic seed phrase you can use [HdWalletKit](https://github.com/horizontalsystems/hd-wallet-kit-android) to convert a word list to a seed.

```kotlin
val words = listOf("mnemonic", "phrase", "words")
val passphrase: String = ""

val seed = Mnemonic().toSeed(words, passphrase)
```

Then you can pass a seed to initialize an instance of *BitcoinKit*

```kotlin
val context = Application()

val bitcoinKit = BitcoinKit(
    context = context,
    seed = seed,
    walletId = "unique_wallet_id",
    syncMode = BitcoinCore.SyncMode.Api(),
    networkType = NetworkType.MainNet,
    confirmationsThreshold = 6,
    purpose = HDWallet.Purpose.BIP84
)
```

#### `purpose`

*bitcoinkit* supports `BIP44`, `BIP49` and `BIP84` wallets. They have different derivation paths, so you need to specify this on kit initialization.

#### `syncMode`

*bitcoinkit* pulls all historical transactions of given account from bitcoin peers according to SPV protocol. This process may take several hours as it needs to download every block header with some transactions to find transactions concerning the accounts addresses. In order to speed up the initial blockchain scan, *bitcoincore* has some optimization options:

- It doesn't download blocks added before the [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) was implemented by wallets, because there were no transactions concerning addresses generated by BIP44 wallets.

- If you set **API()** or **NewWallet()** to *syncMode* parameter, it first requests from an **API**(currently [Blockchain.com](https://blockchain.info)) the hashes of the blocks where there are transactions we need. Then, it downloads those blocks from the bitcoin peers. This reduces the initial synchronization time to several minutes. This also carries some risks that makes it possible for a middle-man attacker to learn about the addresses requested from your IP address. But your funds are totally safe.

If you set **Full()** to *syncMode*, then only decentralized peers are used. Once the initial blockchain scan is completed, the remaining synchronization works with decentralized peers only for all *syncMode*s.

#### Additional parameters:
- `networkType`: Mainnet or Testnet
- `confirmationsThreshold`: Minimum number of confirmations required for an unspent output to be available for use (*default: 6*)

#### Initializing with HD extended key

You can initialize `BitcoinKit` using BIP32 Extended Private/Public Key as follows:

```kotlin
val extendedKey = HDExtendedKey("xprvA1BgyAq84AiAsrMm6DKqwCXDwxLBXq76dpUfuNXNziGMzDxYLjE9AkuYBAQTpt6aJu4nFYamh6BbrRkys5fJcxGd7qixNrpVpPBxui9oYyF")

val bitcoinKit = BitcoinKit(
    context = context,
    extendedKey = extendedKey,
    walletId = "unique_wallet_id",
    syncMode = BitcoinCore.SyncMode.Api(),
    networkType = NetworkType.MainNet,
    confirmationsThreshold = 6
)
```

If you restore with a public extended key, then you only will be able to watch the wallet. You won't be able to send any transactions. This is how the **watch account** feature is implemented.

### Starting and Stopping

*BitcoinKit* requires to be started with `start` command. It will be in synced state as long as it is possible. You can call `stop` to stop it

```kotlin
bitcoinKit.start()
bitcoinKit.stop()
```

### Getting wallet data

#### Balance

Balance is provided in `Satoshis`:

```kotlin
val balance = bitcoinKit.balance

println(balance.spendable)
println(balance.unspendable)
```

Unspendable balance is non-zero if you have UTXO that is currently not spendable due to some custom unlock script. These custom scripts can be implemented as a plugin, like **Hodler**

#### Last Block Info

```kotlin
val blockInfo = bitcoinKit.lastBlockInfo ?: return

println(blockInfo.headerHash)
println(blockInfo.height)
println(blockInfo.timestamp)
```

#### Receive Address

Get an address which you can receive coins to. Receive address is changed each time after you actually get some coins in that address

```kotlin
bitcoinKit.receiveAddress()   // "mgv1KTzGZby57K5EngZVaPdPtphPmEWjiS"
```

#### Transactions

You can get your transactions using `transactions(fromUid: String? = null, type: TransactionFilterType? = null, limit: Int? = null)` method of the *BitcoinKit* instance. It returns *Single<List<TransactionInfo>>*. You'll need to subscribe and get transactions asynchronously. See [RX Single Observers](http://reactivex.io/RxJava/3.x/javadoc/io/reactivex/rxjava3/core/Single.html) for more info.

```kotlin
val disposables = CompositeDisposable()

bitcoinKit.transactions().subscribe { transactionInfos ->
    for (transactionInfo in transactionInfos) {
        println("Uid: ${transactionInfo.uid}")
        println("Hash: ${transactionInfo.transactionHash}")
    }
}.let {
    disposables.add(it)
}
```

- `fromUid` and `limit` parameters can be used for pagination.
- `type` parameter enables to filter transactions by coins flow. You can pass *incoming* OR *outgoing* to get filtered transactions

#### TransactionInfo

A sample dump:

```kotlin
// transactionInfo = {TransactionInfo}
//    amount = 13114
//    blockHeight = 740024
//    conflictingTxHash = null
//    fee = null
//    inputs = {ArrayList} size = 1
//      0 = {TransactionInputInfo}
//          address = "16s6q8dAgLbDT3szEc4nvTh81deRCBtEa1"
//          mine = false
//          value = null
//    outputs = {ArrayList}  size = 2
//      0 = {TransactionOutputInfo}
//          address = "bc1qsg9ul383f8pespcvc8u3katl6gnsr7sjyfe3pc"
//          changeOutput = false
//          mine = true
//          pluginData = null
//          pluginDataString = null
//          pluginId = null
//          value = 13114
//      1 = {TransactionOutputInfo}
//          address = "16VCm8mYhHE3EiELi8GiYEqAjnPu1TSgAV"
//          changeOutput = false
//          mine = false
//          pluginData = null
//          pluginDataString = null
//          pluginId = null
//          value = 1422
//    status = {TransactionStatus} RELAYED
//    timestamp = 1654766137
//    transactionHash = "cadf99db1e145dcfadfa2bc3eacb94831eb6c53d376f4f873aa4ac017b8c7f8f"
//    transactionIndex = 2760
//    type = {TransactionType} Incoming
//    uid = "75934663-3c84-4b38-9b6d-810d3433de17"
```

`uid`

A local unique ID

`type`

- *Incoming*
- *Outgoing*
- *SentToSelf*

`status`

- *NEW* -> transaction is in mempool
- *RELAYED* -> transaction is in block
- *INVALID* -> transaction is not included in block due to an error OR replaced by another one (RBF).

### Sending BTC

```kotlin
bitcoinKit.send(address = "36k1UofZ2iP2NYax9znDCsksajfKeKLLMJ", value = 100000000, feeRate = 10, sortType = TransactionDataSortType.Bip69)
```

This first validates a given address and amount, creates new transaction, then sends it over the peers network. If there's any error with given address/amount or network, it raises an exception.

#### Validate address

```kotlin
bitcoinKit.validateAddress(address = "mrjQyzbX9SiJxRC2mQhT4LvxFEmt9KEeRY")
```

#### Evaluate fee

```kotlin
bitcoinKit.fee(address = "36k1UofZ2iP2NYax9znDCsksajfKeKLLMJ", value = 100000000, feeRate = 10)
```

### Parsing BIP21 URI

You can use `parsePaymentAddress` method to parse a BIP21 URI:

```kotlin
bitcoinKit.parsePaymentAddress("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=50&label=Luke-Jr&message=Donation%20for%20project%20xyz")

// ▿ BitcoinPaymentData
//   - address : "175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"
//   - version : null
//   - amount : 50.0
//   - label : "Luke-Jr"
//   - message : "Donation for project xyz"
//   - parameters : null
```

### Subscribing to BitcoinKit data

Balance, transactions, last blocks synced and kit state are available in real-time. `BitcoinKit.Listener` interface must be implemented and set to *BitcoinKit* instance to receive that.

```kotlin
class Manager(val bitcoinKit: BitcoinKit) : BitcoinKit.Listener {

    init {
        bitcoinKit.listener = this
    }

    override fun onBalanceUpdate(balance: BalanceInfo) {
    }

    override fun onLastBlockInfoUpdate(blockInfo: BlockInfo) {
    }

    override fun onKitStateUpdate(state: BitcoinCore.KitState) {
    }

    override fun onTransactionsUpdate(inserted: List<TransactionInfo>, updated: List<TransactionInfo>) {
    }

    override fun onTransactionsDelete(hashes: List<String>) {
    }

}
```

# bitcoincashkit

## Features

- [x] `Base58` and `Bech32`
- [x] Validation of BCH hard forks
- [x] `ASERT`, `DAA`, `EDA` validations

## Usage

Because BitcoinCash is a fork of Bitcoin, the usage of this library does not differ much from `bitcoinkit`. So we only describe some differences between them.

### Initialization

All BitcoinCash wallets use default [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) derivation path where *coinType* is `145` according to [SLIP44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md). But since it's a fork of Bitcoin, `0` coinType also can be restored.

```kotlin
val context = Application()
val seed = Mnemonic().toSeed(listOf("mnemonic", "phrase", "words"), "")

val bitcoinCashKit = BitcoinCashKit(
        context = context,
        seed = seed,
        walletId = "unique_wallet_id",
        syncMode = BitcoinCore.SyncMode.Api(),
        networkType = NetworkType.MainNet(MainNetBitcoinCash.CoinType.Type145),
        confirmationsThreshold = 6
)
```

# litecoinkit

Usage identical to `bitcoinkit`

# dashkit

## Features

- [x] Instant send
- [x] LLMQ lock, Masternodes validation

## Usage

### Initialization

```kotlin
val context = Application()
val seed = Mnemonic().toSeed(listOf("mnemonic", "phrase", "words"), "")

val dashKit = DashKit(
        context = context,
        seed = seed,
        walletId = "unique_wallet_id",
        syncMode = BitcoinCore.SyncMode.Api(),
        networkType = NetworkType.MainNet,
        confirmationsThreshold = 6
)
```

### DashTransactionInfo

Dash has some transactions marked `instant`. So, instead of `TransactionInfo` object *DashKit* works with `DashTransactionInfo` that has that field and a respective `DashKit.Listener` listener class.

# hodler

`hodler` is a plugin to `bitcoincore`, that makes it possible to lock bitcoins until some time in the future. It relies on [CHECKSEQUENCEVERIFY](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki) and [Relative time-locks](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki). It may be used with other forks of Bitcoin that support them. `UnstooppableWallet` opts in this plugin and enables it for Bitcoin as an experimental feature.

## How it works

To lock funds we create P2SH output where redeem script has `OP_CSV` OpCode that ensures that the input has a proper Sequence Number(`nSequence`) field and that it enables a relative time-lock.

In [this](https://blockstream.info/tx/1cd11e80d04c82d098f19badb153ea12ec84cda408daaadc566cc129f967a435?input:1&expand) sample transaction the second input unlocks such an output. It has a signature, public key and the following redeem script in its scriptSig:

`OP_PUSHBYTES_3 070040 OP_CSV OP_DROP OP_DUP OP_HASH160 OP_PUSHBYTES_20 853316620ed93e4ade18f8218f9aa15dc36c768e OP_EQUALVERIFY OP_CHECKSIG`

- `OP_PUSHBYTES_3 070040 OP_CSV OP_DROP` part ensures that needed amount of time is passed. Specifically `07` part of `070040` bytes says that it's locked for 1 hour. See [here](https://github.com/horizontalsystems/bitcoin-kit-android/blob/master/hodler/src/main/kotlin/io/horizontalsystems/hodler/LockTimeInterval.kt) and [here](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki) for how it's evaluated.
- `OP_DUP OP_HASH160 OP_PUSHBYTES_20 853316620ed93e4ade18f8218f9aa15dc36c768e OP_EQUALVERIFY OP_CHECKSIG` part is the same locking script as of `P2PKH` output, that ensures the spender is the owner of the private key matching the public key hashed to `853316620ed93e4ade18f8218f9aa15dc36c768e`.

### Detection of incoming time-locked funds

When you have such an `P2SH` output, you only have an address and a hash of a redeem script in the output. If you are not aware of incoming time-locked funds in advance, there's no way you can detect that a particular output is yours. For this reason, we add an extra `OP_RETURN` output beside that `P2SH` output as a hint. That output tells us

- ID of the plugin (1 byte): `bitcoincore` can handle multiple plugins like this one.
- Time-lock period (2 bytes)
- Hash of the receiver's public key (20 bytes)

For example, [this](https://blockstream.info/tx/bdc3e995100269c8813f291dd9ea5489d8a17bd163002f70b5abbe05b5dccbd3?expand) is a *hint* output for the input above. It has following data:

`OP_RETURN OP_PUSHNUM_1 OP_PUSHBYTES_2 0700 OP_PUSHBYTES_20 853316620ed93e4ade18f8218f9aa15dc36c768e`

## Limitations

### Locked time periods

This plugin can lock coins for `1 hour`, `1 month`, `half a year` and `1 year`. This is a limitation arising from the need of restoring those outputs using Simplified Payment Verification (SPV) `Bloom Filters`. Since each lock time generates different `P2SH` addresses, it wouldn't be possible to restore those outputs without knowing the exact lock time period in advance. So we generate 4 different addresses for each public key and use them in the bloom filters.

### BTC amount

We allow maximum 0.5 BTC to be locked. We assume that's an acceptable amount to be locked if done unintentionally.

## Prerequisites
* JDK >= 1.8
* Android 6 (minSdkVersion 23) or greater

## Installation
Add the JitPack to module build.gradle
```
repositories {
    maven { url 'https://jitpack.io' }
}
```
Add the following dependency to your build.gradle file:
```
dependencies {
    implementation 'com.github.horizontalsystems:bitcoin-kit-android:master-SNAPSHOT'
}
```

## Example App

All features of the library are used in example project. It can be referred as a starting point for usage of the library.
* [Example App](https://github.com/horizontalsystems/bitcoin-kit-android/tree/master/app)

## Dependencies
* [HDWalletKit](https://github.com/horizontalsystems/hd-wallet-kit-android) - HD Wallet related features, mnemonic phrase

## Contributing

[Contributing](CONTRIBUTING.md)

## License

The `bitcoin-kit-android` is open source and available under the terms of the [MIT License](https://github.com/horizontalsystems/bitcoin-kit-android/blob/master/LICENSE)


# Arend plugin for IntelliJ IDEA

![](https://arend-lang.github.io/assets/images/Logo_byJB.svg)

[![JetBrains incubator project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![Actions Status](https://github.com/JetBrains/intellij-arend/workflows/check/badge.svg)](https://github.com/JetBrains/intellij-arend/actions)
[![Downloads][d-svg]][jb-url]
[![Version][v-svg]][jb-url]

 [d-svg]: https://img.shields.io/jetbrains/plugin/d/11162.svg
 [v-svg]: https://img.shields.io/jetbrains/plugin/v/11162.svg
 [jb-url]: https://plugins.jetbrains.com/plugin/11162

Plugin that implements [Arend](https://github.com/JetBrains/Arend) support
in [IntelliJ IDEA](https://www.jetbrains.com/idea/) and other IntelliJ-based products.
Arend is a theorem prover based on [Homotopy Type Theory](https://ncatlab.org/nlab/show/homotopy+type+theory).
Visit [arend-lang.github.io](https://arend-lang.github.io/) for more information about the Arend language.

## Clone

```
git clone https://github.com/JetBrains/Arend
git clone https://github.com/JetBrains/intellij-arend.git
cd intellij-arend
```

## Building

We use gradle to build the plugin. It comes with a wrapper script (`gradlew` or `gradlew.bat` in
the root of the repository) which downloads appropriate version of gradle
automatically as long as you have JDK (version >= 11) installed.

Common tasks are

  - `./gradlew buildPlugin` — fully build plugin and create an archive at
    `build/distributions` which can be installed into IntelliJ IDEA via `Install
    plugin from disk` action found in **File | Settings | Plugins**.

  - `./gradlew runIde` — run a development IDE with the plugin installed.

  - `./gradlew test` — run all tests.

## Developing

You can get the latest IntelliJ IDEA Community Edition
[here](https://www.jetbrains.com/idea/download/).

To import this project in IntelliJ, use **File | New | Project from Existing Sources**
and select the root directory of the plugin source code.

When hacking on the plugin, you may need the following plugins -

* **[Grammar-Kit](https://plugins.jetbrains.com/plugin/6606-grammar-kit)** -
BNF Grammars and JFlex lexers editor. Readable parser/PSI code generator.
* **[PsiViewer](https://plugins.jetbrains.com/plugin/227-psiviewer)** -
A Program Structure Interface (PSI) tree viewer.


[![forthebadge](https://forthebadge.com/images/badges/60-percent-of-the-time-works-every-time.svg)](https://forthebadge.com)

ChatTriggers is always in development. Although we try to follow standard version conventions
and deprecate old methods before removing them, there may be times where we need to restructure
 something to the point where deprecation is impossible. Modules can and will break at any time.

# About
ChatTriggers is a framework for Minecraft that allows for live scripting and client modification
using JavaScript. We provide libraries, wrappers, objects and more to make your life as a modder
as easy as possible. Even without the proper wrapper, you can still use exposed Minecraft methods
and variables but you will need knowledge of FML mappings. The entire ChatTriggers engine is built
on [Rhino](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino) using Java 8
so you have access to any Rhino methods and functions. Rhino supports _some_ ES6 features,
as can be seen [here](https://mozilla.github.io/rhino/compat/engines.html).

The basic premise of ChatTriggers is that everything is based around Triggers.
From a modding standpoint, Triggers can be thought of as event listeners.
These can range from a chat Trigger that runs on a specific chat event matching criteria to a
render overlay Trigger that runs when the crosshair is being rendered. We are constantly adding
more Triggers and Trigger types as the mod evolves for more integration with Minecraft.

```JavaScript
register("chat", function(name, message, event) {
  cancel(event);
  ChatLib.chat(name + ": " + message);
}).setCriteria("<${name}> ${message}");

register("renderCrosshair", function(event) {
  cancel(event);
  Renderer.drawRect(
    0x50ffffff,
    Renderer.screen.getWidth() / 2 - 1,
    Renderer.screen.getHeight() / 2 - 1,
    2, 2
  );
});
```

You can learn the basics of scripting with ChatTriggers from the [Slate tutorial](https://www.chattriggers.com/slate/) and once you get the basics, check out the [JavaDocs](https://www.chattriggers.com/javadocs/) for a more in depth look at all of the available methods.

# Releases
The [ChatTriggers website](https://www.chattriggers.com/) will always be kept up to date with the latest release. As of beta version 0.6.4, we have started to move the release changelog along with a .jar download (mirror of the website) to the [GitHub releases page](https://github.com/ChatTriggers/ChatTriggers/releases).

# Feature changes
Any major features are moved to separate branches before being merged into master. This will avoid the issue of waiting after a release to fix bugs when we want to be working on new features. Any contributors will have to abide by the same standard. New features get their own branch and bug fixes require a pull request on the master branch.

# Issues
Any issue can be opened using the normal [GitHub issue page](https://github.com/ChatTriggers/ChatTriggers/issues). Issues can be anything from bug reports to feature requests. For us to consider an issue to be valid, it needs a simple but effective title that conveys the problem in a few words and a well thought out and well written description.
### Bug Report
- Should be reproducible
- Needs a step by step guide on how to reproduce
- Any evidence of the bug occurring (e.g. images or video) is welcome
### Feature Request
- Needs a general description of the feature requests
- Specifics on what is being requested (e.g. what class you want it in or what it should do) is highly recommended

Duplicate issues will be merged to avoid too much clutter. If an issue is moved to "next" we will usually comment on it to explain how we expect to implement or fix that issue.

## Special Thanks To

  The Java Profiler jProfiler