parent
c1730c3a17
commit
8a01d595fb
|
|
@ -16,6 +16,7 @@
|
||||||
.cxx
|
.cxx
|
||||||
local.properties
|
local.properties
|
||||||
revoltbuild.properties
|
revoltbuild.properties
|
||||||
|
stoatbuild.properties
|
||||||
sentry.properties
|
sentry.properties
|
||||||
/.kotlin/sessions
|
/.kotlin/sessions
|
||||||
app/src/main/assets/embedded
|
app/src/main/assets/embedded
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Revolt
|
Stoat
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<rect width="500" height="500" rx="250" fill="url(#paint0_linear_204_8)"/>
|
|
||||||
<path d="M170.057 373C170.057 297.671 170.057 248.292 170.057 184.167L122 127H277.429C295.891 127 312.046 130.323 325.893 136.97C339.739 143.616 350.509 153.186 358.202 165.678C365.894 178.17 369.741 193.145 369.741 210.602C369.741 228.219 365.773 243.073 357.837 255.165C349.983 267.257 338.93 276.386 324.678 282.552C310.507 288.718 293.948 291.801 275 291.801H210.868V239.91H261.396C269.332 239.91 276.093 238.949 281.68 237.027C287.349 235.025 291.681 231.862 294.677 227.538C297.754 223.214 299.292 217.568 299.292 210.602C299.292 203.555 297.754 197.829 294.677 193.425C291.681 188.94 287.349 185.657 281.68 183.575C276.093 181.413 269.332 180.332 261.396 180.332H237.59V373H170.057ZM315.811 260.09L378 373H304.637L243.906 260.09H315.811Z" fill="#FF005C"/>
|
|
||||||
<defs>
|
|
||||||
<linearGradient id="paint0_linear_204_8" x1="17.4479" y1="13.8889" x2="589.73" y2="199.249" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#070C1A"/>
|
|
||||||
<stop offset="1" stop-color="#262B37"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB |
20
README.md
20
README.md
|
|
@ -1,6 +1,6 @@
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<h1>Revolt for Android</h1>
|
<h1>Stoat for Android</h1>
|
||||||
<p>Official <a href="https://revolt.chat">Revolt</a> Android app.</p>
|
<p>Official <a href="https://stoat.chat">Stoat</a> Android app.</p>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
<div>
|
<div>
|
||||||
<img src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" alt="Get it on Google Play" width="200">
|
<img src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" alt="Get it on Google Play" width="200">
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
The codebase includes the app itself, as well as an internal library for interacting with the Revolt
|
The codebase includes the app itself, as well as an internal library for interacting with the Stoat
|
||||||
API. The app is written in Kotlin, and wholly
|
API. The app is written in Kotlin, and wholly
|
||||||
uses [Jetpack Compose](https://developer.android.com/jetpack/compose).
|
uses [Jetpack Compose](https://developer.android.com/jetpack/compose).
|
||||||
|
|
||||||
|
|
@ -28,20 +28,20 @@ uses [Jetpack Compose](https://developer.android.com/jetpack/compose).
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
### Revolt for Android
|
### Stoat for Android
|
||||||
|
|
||||||
- [Roadmap](https://op.revolt.wtf/projects/revolt-for-android/work_packages)
|
- [Roadmap](https://op.revolt.wtf/projects/revolt-for-android/work_packages)
|
||||||
- [Revolt for Android Technical Documentation](https://revoltchat.github.io/android/)
|
- [Stoat for Android Technical Documentation](https://revoltchat.github.io/android/)
|
||||||
- [Android-specific Contribution Guide](https://revoltchat.github.io/android/contributing/guidelines/)
|
- [Android-specific Contribution Guide](https://revoltchat.github.io/android/contributing/guidelines/)
|
||||||
—**read carefully before contributing!**
|
—**read carefully before contributing!**
|
||||||
|
|
||||||
### Revolt
|
### Stoat
|
||||||
|
|
||||||
- [Revolt Project Board](https://github.com/revoltchat/revolt/discussions) (Submit feature requests
|
- [Stoat Project Board](https://github.com/revoltchat/revolt/discussions) (Submit feature requests
|
||||||
here)
|
here)
|
||||||
- [Revolt Development Server](https://app.revolt.chat/invite/API)
|
- [Stoat Development Server](https://app.revolt.chat/invite/API)
|
||||||
- [Revolt Server](https://app.revolt.chat/invite/Testers)
|
- [Stoat Server](https://app.revolt.chat/invite/Testers)
|
||||||
- [General Revolt Contribution Guide](https://developers.revolt.chat/contrib.html)
|
- [General Stoat Contribution Guide](https://developers.revolt.chat/contrib.html)
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ val accompanistVersion = "0.34.0"
|
||||||
val okhttpVersion = "4.12.0"
|
val okhttpVersion = "4.12.0"
|
||||||
val navVersion = "2.9.0"
|
val navVersion = "2.9.0"
|
||||||
val hiltVersion = "2.57"
|
val hiltVersion = "2.57"
|
||||||
val glideVersion = "4.16.0"
|
val glideVersion = "5.0.5"
|
||||||
val ktorVersion = "3.0.0-beta-2"
|
val ktorVersion = "3.0.0-beta-2"
|
||||||
val media3Version = "1.7.1"
|
val media3Version = "1.7.1"
|
||||||
val material3Version = "1.4.0-alpha15"
|
val material3Version = "1.4.0-alpha15"
|
||||||
|
|
@ -67,13 +67,14 @@ fun property(fileName: String, propertyName: String, fallbackEnv: String? = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calls property but with revoltbuild.properties as the first argument
|
// Calls property but with stoatbuild.properties as the first argument
|
||||||
fun buildproperty(propertyName: String, fallbackEnv: String? = null): String? {
|
fun buildproperty(propertyName: String, fallbackEnv: String? = null): String? {
|
||||||
return property("revoltbuild.properties", propertyName, fallbackEnv)
|
return property("stoatbuild.properties", propertyName, fallbackEnv)
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk = 36
|
compileSdk = 36
|
||||||
|
namespace = "chat.stoat"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "chat.revolt"
|
applicationId = "chat.revolt"
|
||||||
|
|
@ -159,7 +160,6 @@ android {
|
||||||
androidResources {
|
androidResources {
|
||||||
generateLocaleConfig = true
|
generateLocaleConfig = true
|
||||||
}
|
}
|
||||||
namespace = "chat.revolt"
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
path(file("src/main/cpp/CMakeLists.txt"))
|
path(file("src/main/cpp/CMakeLists.txt"))
|
||||||
|
|
@ -241,6 +241,7 @@ dependencies {
|
||||||
// Glide - Image Loading
|
// Glide - Image Loading
|
||||||
implementation("com.github.bumptech.glide:glide:$glideVersion")
|
implementation("com.github.bumptech.glide:glide:$glideVersion")
|
||||||
implementation("com.github.bumptech.glide:compose:1.0.0-beta01")
|
implementation("com.github.bumptech.glide:compose:1.0.0-beta01")
|
||||||
|
implementation("com.github.bumptech.glide:okhttp3-integration:5.0.5")
|
||||||
ksp("com.github.bumptech.glide:ksp:$glideVersion")
|
ksp("com.github.bumptech.glide:ksp:$glideVersion")
|
||||||
|
|
||||||
// AboutLibraries - automated OSS library attribution
|
// AboutLibraries - automated OSS library attribution
|
||||||
|
|
@ -313,9 +314,6 @@ dependencies {
|
||||||
// Square Logcat
|
// Square Logcat
|
||||||
implementation("com.squareup.logcat:logcat:0.1")
|
implementation("com.squareup.logcat:logcat:0.1")
|
||||||
|
|
||||||
// Librevolt
|
|
||||||
implementation("librevolt:librevolt-jvm:0.1.0")
|
|
||||||
|
|
||||||
// Testing
|
// Testing
|
||||||
androidTestImplementation("androidx.test:runner:$androidXTestVersion")
|
androidTestImplementation("androidx.test:runner:$androidXTestVersion")
|
||||||
androidTestImplementation("androidx.test:rules:$androidXTestVersion")
|
androidTestImplementation("androidx.test:rules:$androidXTestVersion")
|
||||||
|
|
@ -344,7 +342,7 @@ aboutLibraries {
|
||||||
sqldelight {
|
sqldelight {
|
||||||
databases {
|
databases {
|
||||||
create("Database") {
|
create("Database") {
|
||||||
packageName.set("chat.revolt.persistence")
|
packageName.set("chat.stoat.persistence")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,4 +109,4 @@
|
||||||
public <fields>;
|
public <fields>;
|
||||||
}
|
}
|
||||||
|
|
||||||
-keep class chat.revolt.ndk.AstNode { *; }
|
-keep class chat.stoat.ndk.AstNode { *; }
|
||||||
|
|
@ -32,8 +32,8 @@
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:name=".RevoltApplication"
|
android:name=".StoatApplication"
|
||||||
android:theme="@style/Theme.Revolt"
|
android:theme="@style/Theme.Stoat"
|
||||||
android:enableOnBackInvokedCallback="true"
|
android:enableOnBackInvokedCallback="true"
|
||||||
tools:targetApi="tiramisu">
|
tools:targetApi="tiramisu">
|
||||||
<provider
|
<provider
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:configChanges="orientation|screenSize|colorMode"
|
android:configChanges="orientation|screenSize|colorMode"
|
||||||
android:windowSoftInputMode="adjustResize"
|
android:windowSoftInputMode="adjustResize"
|
||||||
android:theme="@style/Theme.Revolt">
|
android:theme="@style/Theme.Stoat">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
|
@ -80,8 +80,9 @@
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.InviteActivity"
|
android:name=".activities.InviteActivity"
|
||||||
android:theme="@style/Theme.Revolt"
|
android:theme="@style/Theme.Stoat"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
<!-- Revolt invite links -->
|
||||||
<intent-filter android:autoVerify="true">
|
<intent-filter android:autoVerify="true">
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
|
@ -106,6 +107,37 @@
|
||||||
|
|
||||||
<data android:host="rvlt.gg" />
|
<data android:host="rvlt.gg" />
|
||||||
|
|
||||||
|
<uri-relative-filter-group
|
||||||
|
android:allow="false"
|
||||||
|
tools:targetApi="35">
|
||||||
|
<data android:pathPrefix="/discover/" />
|
||||||
|
</uri-relative-filter-group>
|
||||||
|
</intent-filter>
|
||||||
|
<!-- Stoat invite links -->
|
||||||
|
<intent-filter android:autoVerify="true">
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="http" />
|
||||||
|
<data android:scheme="https" />
|
||||||
|
|
||||||
|
<data android:host="stoat.chat" />
|
||||||
|
|
||||||
|
<data android:pathPrefix="/invite/" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter android:autoVerify="true">
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="http" />
|
||||||
|
<data android:scheme="https" />
|
||||||
|
|
||||||
|
<data android:host="stt.gg" />
|
||||||
|
|
||||||
<uri-relative-filter-group
|
<uri-relative-filter-group
|
||||||
android:allow="false"
|
android:allow="false"
|
||||||
tools:targetApi="35">
|
tools:targetApi="35">
|
||||||
|
|
@ -116,7 +148,7 @@
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.ShareTargetActivity"
|
android:name=".activities.ShareTargetActivity"
|
||||||
android:theme="@style/Theme.Revolt"
|
android:theme="@style/Theme.Stoat"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
|
@ -132,17 +164,17 @@
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.media.ImageViewActivity"
|
android:name=".activities.media.ImageViewActivity"
|
||||||
android:theme="@style/Theme.Revolt" />
|
android:theme="@style/Theme.Stoat" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.media.VideoViewActivity"
|
android:name=".activities.media.VideoViewActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:theme="@style/Theme.Revolt" />
|
android:theme="@style/Theme.Stoat" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.voice.IncomingActivity"
|
android:name=".activities.voice.IncomingActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:theme="@style/Theme.Revolt" />
|
android:theme="@style/Theme.Stoat" />
|
||||||
|
|
||||||
<!-- Backport photo picker via Google Play Services -->
|
<!-- Backport photo picker via Google Play Services -->
|
||||||
<service
|
<service
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ cmake_minimum_required(VERSION 3.22.1)
|
||||||
# Since this is the top level CMakeLists.txt, the project name is also accessible
|
# Since this is the top level CMakeLists.txt, the project name is also accessible
|
||||||
# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
|
# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
|
||||||
# build script scope).
|
# build script scope).
|
||||||
project("revolt")
|
project("stoat")
|
||||||
|
|
||||||
# Compile cmark in external/cmark
|
# Compile cmark in external/cmark
|
||||||
add_subdirectory(external/cmark)
|
add_subdirectory(external/cmark)
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ namespace Stendal {
|
||||||
constructArrayListMethod = env->GetMethodID(localArrayListClass, "<init>", "(I)V");
|
constructArrayListMethod = env->GetMethodID(localArrayListClass, "<init>", "(I)V");
|
||||||
addArrayListMethod = env->GetMethodID(localArrayListClass, "add", "(Ljava/lang/Object;)Z");
|
addArrayListMethod = env->GetMethodID(localArrayListClass, "add", "(Ljava/lang/Object;)Z");
|
||||||
|
|
||||||
jclass localAstNodeClass = env->FindClass("chat/revolt/ndk/AstNode");
|
jclass localAstNodeClass = env->FindClass("chat/stoat/ndk/AstNode");
|
||||||
astNodeClass = (jclass) env->NewGlobalRef(localAstNodeClass);
|
astNodeClass = (jclass) env->NewGlobalRef(localAstNodeClass);
|
||||||
astNodeConstructor = env->GetMethodID(localAstNodeClass, "<init>",
|
astNodeConstructor = env->GetMethodID(localAstNodeClass, "<init>",
|
||||||
STENDAL_ASTNODE_CONSTRUCTOR_SIGNATURE);
|
STENDAL_ASTNODE_CONSTRUCTOR_SIGNATURE);
|
||||||
|
|
@ -141,12 +141,12 @@ namespace Stendal {
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_chat_revolt_ndk_Stendal_init(JNIEnv *env, [[maybe_unused]] jobject thiz) {
|
Java_chat_stoat_ndk_Stendal_init(JNIEnv *env, [[maybe_unused]] jobject thiz) {
|
||||||
Stendal::init(env);
|
Stendal::init(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jobject JNICALL
|
extern "C" JNIEXPORT jobject JNICALL
|
||||||
Java_chat_revolt_ndk_Stendal_render(JNIEnv *env, [[maybe_unused]] jobject thiz, jstring input) {
|
Java_chat_stoat_ndk_Stendal_render(JNIEnv *env, [[maybe_unused]] jobject thiz, jstring input) {
|
||||||
const char *inputStr = env->GetStringUTFChars(input, nullptr);
|
const char *inputStr = env->GetStringUTFChars(input, nullptr);
|
||||||
cmark_node *doc = cmark_parse_document(inputStr, strlen(inputStr),
|
cmark_node *doc = cmark_parse_document(inputStr, strlen(inputStr),
|
||||||
CMARK_OPT_DEFAULT | CMARK_OPT_HARDBREAKS |
|
CMARK_OPT_DEFAULT | CMARK_OPT_HARDBREAKS |
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package chat.revolt.api.routes.channel
|
|
||||||
|
|
||||||
import chat.revolt.api.RevoltHttp
|
|
||||||
import chat.revolt.api.api
|
|
||||||
import io.ktor.client.request.delete
|
|
||||||
import io.ktor.client.request.put
|
|
||||||
|
|
||||||
suspend fun react(channelId: String, messageId: String, emoji: String) {
|
|
||||||
RevoltHttp.put("/channels/$channelId/messages/$messageId/reactions/$emoji".api())
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun unreact(channelId: String, messageId: String, emoji: String) {
|
|
||||||
RevoltHttp.delete("/channels/$channelId/messages/$messageId/reactions/$emoji".api())
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
package chat.revolt.api.routes.custom
|
|
||||||
|
|
||||||
import chat.revolt.api.RevoltHttp
|
|
||||||
import chat.revolt.api.RevoltJson
|
|
||||||
import chat.revolt.api.api
|
|
||||||
import chat.revolt.api.schemas.Emoji
|
|
||||||
import io.ktor.client.request.get
|
|
||||||
import io.ktor.client.statement.bodyAsText
|
|
||||||
|
|
||||||
suspend fun fetchEmoji(id: String): Emoji {
|
|
||||||
val response = RevoltHttp.get("/custom/emoji/$id".api()).bodyAsText()
|
|
||||||
return RevoltJson.decodeFromString(
|
|
||||||
Emoji.serializer(),
|
|
||||||
response
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
package chat.revolt.api.routes.invites
|
|
||||||
|
|
||||||
import chat.revolt.api.RevoltError
|
|
||||||
import chat.revolt.api.RevoltHttp
|
|
||||||
import chat.revolt.api.RevoltJson
|
|
||||||
import chat.revolt.api.api
|
|
||||||
import chat.revolt.api.schemas.Invite
|
|
||||||
import chat.revolt.api.schemas.InviteJoined
|
|
||||||
import chat.revolt.api.schemas.RsResult
|
|
||||||
import io.ktor.client.request.get
|
|
||||||
import io.ktor.client.request.post
|
|
||||||
import io.ktor.client.statement.bodyAsText
|
|
||||||
import kotlinx.serialization.SerializationException
|
|
||||||
|
|
||||||
suspend fun fetchInviteByCode(code: String): RsResult<Invite, RevoltError> {
|
|
||||||
val response = RevoltHttp.get("/invites/$code".api())
|
|
||||||
.bodyAsText()
|
|
||||||
|
|
||||||
try {
|
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
|
||||||
if (error.type != "Server") return RsResult.err(error)
|
|
||||||
} catch (e: SerializationException) {
|
|
||||||
// Not an error
|
|
||||||
}
|
|
||||||
|
|
||||||
val invite = RevoltJson.decodeFromString(Invite.serializer(), response)
|
|
||||||
return RsResult.ok(invite)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun joinInviteByCode(code: String): RsResult<InviteJoined, RevoltError> {
|
|
||||||
val response = RevoltHttp.post("/invites/$code".api())
|
|
||||||
.bodyAsText()
|
|
||||||
|
|
||||||
try {
|
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
|
||||||
if (error.type != "Server") return RsResult.err(error)
|
|
||||||
} catch (e: SerializationException) {
|
|
||||||
// Not an error
|
|
||||||
}
|
|
||||||
|
|
||||||
val invite = RevoltJson.decodeFromString(InviteJoined.serializer(), response)
|
|
||||||
return RsResult.ok(invite)
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
package chat.revolt.api.routes.microservices.health
|
|
||||||
|
|
||||||
import chat.revolt.api.RevoltHttp
|
|
||||||
import chat.revolt.api.RevoltJson
|
|
||||||
import chat.revolt.api.schemas.HealthNotice
|
|
||||||
import io.ktor.client.request.get
|
|
||||||
import io.ktor.client.statement.bodyAsText
|
|
||||||
|
|
||||||
suspend fun healthCheck(): HealthNotice {
|
|
||||||
val response = RevoltHttp.get("https://health.revolt.chat/api/health").bodyAsText()
|
|
||||||
return RevoltJson.decodeFromString(HealthNotice.serializer(), response)
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
package chat.revolt.api.routes.microservices.january
|
|
||||||
|
|
||||||
import chat.revolt.api.REVOLT_JANUARY
|
|
||||||
import java.net.URLEncoder
|
|
||||||
|
|
||||||
fun asJanuaryProxyUrl(url: String): String {
|
|
||||||
return "$REVOLT_JANUARY/proxy?url=${URLEncoder.encode(url, "utf-8")}"
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package chat.revolt.api.routes.user
|
|
||||||
|
|
||||||
import chat.revolt.api.RevoltError
|
|
||||||
import chat.revolt.api.RevoltHttp
|
|
||||||
import chat.revolt.api.RevoltJson
|
|
||||||
import chat.revolt.api.api
|
|
||||||
import chat.revolt.api.schemas.Channel
|
|
||||||
import io.ktor.client.request.get
|
|
||||||
import io.ktor.client.statement.bodyAsText
|
|
||||||
import kotlinx.serialization.SerializationException
|
|
||||||
|
|
||||||
suspend fun openDM(userId: String): Channel {
|
|
||||||
val response = RevoltHttp.get("/users/$userId/dm".api())
|
|
||||||
.bodyAsText()
|
|
||||||
|
|
||||||
try {
|
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
|
||||||
throw Error(error.type)
|
|
||||||
} catch (e: SerializationException) {
|
|
||||||
// Not an error
|
|
||||||
}
|
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(Channel.serializer(), response)
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
package chat.revolt.screens.labs.ui.sandbox
|
|
||||||
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.text.SpanStyle
|
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
|
||||||
import androidx.navigation.NavController
|
|
||||||
import chat.revolt.settings.dsl.SettingsPage
|
|
||||||
import chat.revolt.ui.theme.FragmentMono
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun CoreLibSandbox(navController: NavController) {
|
|
||||||
var greeting by remember { mutableStateOf("<no greeting>") }
|
|
||||||
|
|
||||||
SettingsPage(
|
|
||||||
navController,
|
|
||||||
title = {
|
|
||||||
Text(
|
|
||||||
text = buildAnnotatedString {
|
|
||||||
pushStyle(SpanStyle(fontFamily = FragmentMono))
|
|
||||||
append("librevolt")
|
|
||||||
pop()
|
|
||||||
append(" Sample")
|
|
||||||
},
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Button(onClick = {
|
|
||||||
greeting = librevolt.greet()
|
|
||||||
}) {
|
|
||||||
Text("Greet")
|
|
||||||
}
|
|
||||||
Text(greeting)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt
|
package chat.stoat
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.os.StrictMode
|
import android.os.StrictMode
|
||||||
|
|
@ -8,9 +8,9 @@ import logcat.AndroidLogcatLogger
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
|
|
||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
class RevoltApplication : Application() {
|
class StoatApplication : Application() {
|
||||||
companion object {
|
companion object {
|
||||||
lateinit var instance: RevoltApplication
|
lateinit var instance: StoatApplication
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.activities
|
package chat.stoat.activities
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
|
@ -46,19 +46,19 @@ import androidx.core.view.WindowCompat
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.stoat.api.STOAT_FILES
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.routes.invites.fetchInviteByCode
|
import chat.stoat.api.routes.invites.fetchInviteByCode
|
||||||
import chat.revolt.api.routes.invites.joinInviteByCode
|
import chat.stoat.api.routes.invites.joinInviteByCode
|
||||||
import chat.revolt.api.schemas.Invite
|
import chat.stoat.api.schemas.Invite
|
||||||
import chat.revolt.api.schemas.InviteJoined
|
import chat.stoat.api.schemas.InviteJoined
|
||||||
import chat.revolt.api.schemas.RsResult
|
import chat.stoat.api.schemas.RsResult
|
||||||
import chat.revolt.api.settings.LoadedSettings
|
import chat.stoat.api.settings.LoadedSettings
|
||||||
import chat.revolt.api.settings.SyncedSettings
|
import chat.stoat.api.settings.SyncedSettings
|
||||||
import chat.revolt.composables.generic.IconPlaceholder
|
import chat.stoat.composables.generic.IconPlaceholder
|
||||||
import chat.revolt.composables.generic.RemoteImage
|
import chat.stoat.composables.generic.RemoteImage
|
||||||
import chat.revolt.ui.theme.RevoltTheme
|
import chat.stoat.ui.theme.StoatTheme
|
||||||
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
|
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
|
||||||
import com.bumptech.glide.integration.compose.GlideImage
|
import com.bumptech.glide.integration.compose.GlideImage
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -90,19 +90,19 @@ class InviteViewModel : ViewModel() {
|
||||||
_loadingFinished = loadingFinished
|
_loadingFinished = loadingFinished
|
||||||
}
|
}
|
||||||
|
|
||||||
private var _inviteResult by mutableStateOf<RsResult<Invite, RevoltError>?>(null)
|
private var _inviteResult by mutableStateOf<RsResult<Invite, StoatAPIError>?>(null)
|
||||||
val inviteResult: RsResult<Invite, RevoltError>?
|
val inviteResult: RsResult<Invite, StoatAPIError>?
|
||||||
get() = _inviteResult
|
get() = _inviteResult
|
||||||
|
|
||||||
fun setInviteResult(inviteResult: RsResult<Invite, RevoltError>?) {
|
fun setInviteResult(inviteResult: RsResult<Invite, StoatAPIError>?) {
|
||||||
_inviteResult = inviteResult
|
_inviteResult = inviteResult
|
||||||
}
|
}
|
||||||
|
|
||||||
private var _joinResult by mutableStateOf<RsResult<InviteJoined, RevoltError>?>(null)
|
private var _joinResult by mutableStateOf<RsResult<InviteJoined, StoatAPIError>?>(null)
|
||||||
val joinResult: RsResult<InviteJoined, RevoltError>?
|
val joinResult: RsResult<InviteJoined, StoatAPIError>?
|
||||||
get() = _joinResult
|
get() = _joinResult
|
||||||
|
|
||||||
fun setJoinResult(joinResult: RsResult<InviteJoined, RevoltError>?) {
|
fun setJoinResult(joinResult: RsResult<InviteJoined, StoatAPIError>?) {
|
||||||
_joinResult = joinResult
|
_joinResult = joinResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,7 +144,7 @@ fun InviteScreen(
|
||||||
val inviteValid = if (viewModel.loadingFinished) (viewModel.inviteResult?.ok ?: false) else null
|
val inviteValid = if (viewModel.loadingFinished) (viewModel.inviteResult?.ok ?: false) else null
|
||||||
val invite = viewModel.inviteResult?.value
|
val invite = viewModel.inviteResult?.value
|
||||||
|
|
||||||
RevoltTheme(
|
StoatTheme(
|
||||||
requestedTheme = LoadedSettings.theme,
|
requestedTheme = LoadedSettings.theme,
|
||||||
colourOverrides = SyncedSettings.android.colourOverrides
|
colourOverrides = SyncedSettings.android.colourOverrides
|
||||||
) {
|
) {
|
||||||
|
|
@ -180,7 +180,7 @@ fun InviteScreen(
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
GlideImage(
|
GlideImage(
|
||||||
model = "$REVOLT_FILES/banners/${invite?.serverBanner?.id}/${invite?.serverBanner?.filename}",
|
model = "$STOAT_FILES/banners/${invite?.serverBanner?.id}/${invite?.serverBanner?.filename}",
|
||||||
contentScale = ContentScale.Crop,
|
contentScale = ContentScale.Crop,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -205,7 +205,7 @@ fun InviteScreen(
|
||||||
) {
|
) {
|
||||||
if (invite?.serverIcon != null) {
|
if (invite?.serverIcon != null) {
|
||||||
RemoteImage(
|
RemoteImage(
|
||||||
url = "$REVOLT_FILES/icons/${invite.serverIcon.id}/${invite.serverIcon.filename}",
|
url = "$STOAT_FILES/icons/${invite.serverIcon.id}/${invite.serverIcon.filename}",
|
||||||
allowAnimation = false,
|
allowAnimation = false,
|
||||||
description = viewModel.inviteResult?.value?.serverName
|
description = viewModel.inviteResult?.value?.serverName
|
||||||
?: stringResource(id = R.string.unknown),
|
?: stringResource(id = R.string.unknown),
|
||||||
|
|
@ -274,7 +274,7 @@ fun InviteScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun InvalidInviteError(error: RevoltError? = null, onDismissRequest: () -> Unit) {
|
fun InvalidInviteError(error: StoatAPIError? = null, onDismissRequest: () -> Unit) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
icon = {
|
icon = {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.activities
|
package chat.stoat.activities
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
@ -72,57 +72,57 @@ import androidx.lifecycle.viewModelScope
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import chat.revolt.BuildConfig
|
import chat.stoat.BuildConfig
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.RevoltApplication
|
import chat.stoat.StoatApplication
|
||||||
import chat.revolt.api.HitRateLimitException
|
import chat.stoat.api.HitRateLimitException
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import chat.revolt.api.routes.microservices.geo.queryGeo
|
import chat.stoat.api.routes.microservices.geo.queryGeo
|
||||||
import chat.revolt.api.routes.microservices.health.healthCheck
|
import chat.stoat.api.routes.microservices.health.healthCheck
|
||||||
import chat.revolt.api.routes.onboard.needsOnboarding
|
import chat.stoat.api.routes.onboard.needsOnboarding
|
||||||
import chat.revolt.api.schemas.HealthNotice
|
import chat.stoat.api.schemas.HealthNotice
|
||||||
import chat.revolt.api.settings.Experiments
|
import chat.stoat.api.settings.Experiments
|
||||||
import chat.revolt.api.settings.GeoStateProvider
|
import chat.stoat.api.settings.GeoStateProvider
|
||||||
import chat.revolt.api.settings.LoadedSettings
|
import chat.stoat.api.settings.LoadedSettings
|
||||||
import chat.revolt.api.settings.SyncedSettings
|
import chat.stoat.api.settings.SyncedSettings
|
||||||
import chat.revolt.composables.generic.HealthAlert
|
import chat.stoat.composables.generic.HealthAlert
|
||||||
import chat.revolt.composables.voice.VoicePermissionSwitch
|
import chat.stoat.composables.voice.VoicePermissionSwitch
|
||||||
import chat.revolt.composables.voice.VoiceSheet
|
import chat.stoat.composables.voice.VoiceSheet
|
||||||
import chat.revolt.material.EasingTokens
|
import chat.stoat.material.EasingTokens
|
||||||
import chat.revolt.ndk.NativeLibraries
|
import chat.stoat.ndk.NativeLibraries
|
||||||
import chat.revolt.persistence.KVStorage
|
import chat.stoat.persistence.KVStorage
|
||||||
import chat.revolt.screens.DefaultDestinationScreen
|
import chat.stoat.screens.DefaultDestinationScreen
|
||||||
import chat.revolt.screens.about.AboutScreen
|
import chat.stoat.screens.about.AboutScreen
|
||||||
import chat.revolt.screens.about.AttributionScreen
|
import chat.stoat.screens.about.AttributionScreen
|
||||||
import chat.revolt.screens.chat.ChatRouterScreen
|
import chat.stoat.screens.chat.ChatRouterScreen
|
||||||
import chat.revolt.screens.chat.views.channel.ChannelScreen
|
import chat.stoat.screens.chat.views.channel.ChannelScreen
|
||||||
import chat.revolt.screens.create.CreateGroupScreen
|
import chat.stoat.screens.create.CreateGroupScreen
|
||||||
import chat.revolt.screens.labs.LabsRootScreen
|
import chat.stoat.screens.labs.LabsRootScreen
|
||||||
import chat.revolt.screens.login.LoginGreetingScreen
|
import chat.stoat.screens.login.LoginGreetingScreen
|
||||||
import chat.revolt.screens.login.LoginScreen
|
import chat.stoat.screens.login.LoginScreen
|
||||||
import chat.revolt.screens.login.MfaScreen
|
import chat.stoat.screens.login.MfaScreen
|
||||||
import chat.revolt.screens.login2.InitScreen
|
import chat.stoat.screens.login2.InitScreen
|
||||||
import chat.revolt.screens.main.MainScreen
|
import chat.stoat.screens.main.MainScreen
|
||||||
import chat.revolt.screens.register.OnboardingScreen
|
import chat.stoat.screens.register.OnboardingScreen
|
||||||
import chat.revolt.screens.register.RegisterDetailsScreen
|
import chat.stoat.screens.register.RegisterDetailsScreen
|
||||||
import chat.revolt.screens.register.RegisterGreetingScreen
|
import chat.stoat.screens.register.RegisterGreetingScreen
|
||||||
import chat.revolt.screens.register.RegisterVerifyScreen
|
import chat.stoat.screens.register.RegisterVerifyScreen
|
||||||
import chat.revolt.screens.services.DiscoverScreen
|
import chat.stoat.screens.services.DiscoverScreen
|
||||||
import chat.revolt.screens.settings.AppearanceSettingsScreen
|
import chat.stoat.screens.settings.AppearanceSettingsScreen
|
||||||
import chat.revolt.screens.settings.ChangelogsSettingsScreen
|
import chat.stoat.screens.settings.ChangelogsSettingsScreen
|
||||||
import chat.revolt.screens.settings.ChatSettingsScreen
|
import chat.stoat.screens.settings.ChatSettingsScreen
|
||||||
import chat.revolt.screens.settings.DebugSettingsScreen
|
import chat.stoat.screens.settings.DebugSettingsScreen
|
||||||
import chat.revolt.screens.settings.ExperimentsSettingsScreen
|
import chat.stoat.screens.settings.ExperimentsSettingsScreen
|
||||||
import chat.revolt.screens.settings.LanguagePickerSettingsScreen
|
import chat.stoat.screens.settings.LanguagePickerSettingsScreen
|
||||||
import chat.revolt.screens.settings.ProfileSettingsScreen
|
import chat.stoat.screens.settings.ProfileSettingsScreen
|
||||||
import chat.revolt.screens.settings.SessionSettingsScreen
|
import chat.stoat.screens.settings.SessionSettingsScreen
|
||||||
import chat.revolt.screens.settings.SettingsScreen
|
import chat.stoat.screens.settings.SettingsScreen
|
||||||
import chat.revolt.screens.settings.channel.ChannelSettingsHome
|
import chat.stoat.screens.settings.channel.ChannelSettingsHome
|
||||||
import chat.revolt.screens.settings.channel.ChannelSettingsOverview
|
import chat.stoat.screens.settings.channel.ChannelSettingsOverview
|
||||||
import chat.revolt.screens.settings.channel.ChannelSettingsPermissions
|
import chat.stoat.screens.settings.channel.ChannelSettingsPermissions
|
||||||
import chat.revolt.ui.theme.RevoltTheme
|
import chat.stoat.ui.theme.StoatTheme
|
||||||
import com.google.android.material.color.DynamicColors
|
import com.google.android.material.color.DynamicColors
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
|
@ -161,9 +161,9 @@ class MainActivityViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun canReachRevolt(): Boolean {
|
private suspend fun canReachStoat(): Boolean {
|
||||||
try {
|
try {
|
||||||
val res = RevoltHttp.get("/".api())
|
val res = StoatHttp.get("/".api())
|
||||||
return res.status.value == 200
|
return res.status.value == 200
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return false
|
return false
|
||||||
|
|
@ -218,17 +218,17 @@ class MainActivityViewModel @Inject constructor(
|
||||||
|
|
||||||
Log.d(
|
Log.d(
|
||||||
"MainActivity",
|
"MainActivity",
|
||||||
"We have a session token, checking if it's valid and if we can still reach Revolt"
|
"We have a session token, checking if it's valid and if we can still reach Stoat"
|
||||||
)
|
)
|
||||||
|
|
||||||
val canReachRevolt = canReachRevolt()
|
val canReachStoat = canReachStoat()
|
||||||
val valid = try {
|
val valid = try {
|
||||||
RevoltAPI.checkSessionToken(token)
|
StoatAPI.checkSessionToken(token)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canReachRevolt && !valid) {
|
if (canReachStoat && !valid) {
|
||||||
Log.d("MainActivity", "Session token is invalid, could not log in")
|
Log.d("MainActivity", "Session token is invalid, could not log in")
|
||||||
couldNotLogIn.emit(true)
|
couldNotLogIn.emit(true)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -255,8 +255,8 @@ class MainActivityViewModel @Inject constructor(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Log.d("MainActivity", "Onboarding state is complete, logging in")
|
Log.d("MainActivity", "Onboarding state is complete, logging in")
|
||||||
RevoltAPI.loginAs(token)
|
StoatAPI.loginAs(token)
|
||||||
RevoltAPI.setSessionId(id)
|
StoatAPI.setSessionId(id)
|
||||||
if (Experiments.usePolar.isEnabled) {
|
if (Experiments.usePolar.isEnabled) {
|
||||||
startWithDestination("main")
|
startWithDestination("main")
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -331,7 +331,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
DynamicColors.applyToActivityIfAvailable(this)
|
DynamicColors.applyToActivityIfAvailable(this)
|
||||||
DynamicColors.applyToActivitiesIfAvailable(RevoltApplication.instance)
|
DynamicColors.applyToActivitiesIfAvailable(StoatApplication.instance)
|
||||||
@Suppress("DEPRECATION") // We are fixing a bug in the splash screen
|
@Suppress("DEPRECATION") // We are fixing a bug in the splash screen
|
||||||
window.statusBarColor = Color.Transparent.toArgb()
|
window.statusBarColor = Color.Transparent.toArgb()
|
||||||
}
|
}
|
||||||
|
|
@ -340,7 +340,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
override fun onConfigurationChanged(newConfig: android.content.res.Configuration) {
|
override fun onConfigurationChanged(newConfig: android.content.res.Configuration) {
|
||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
DynamicColors.applyToActivityIfAvailable(this)
|
DynamicColors.applyToActivityIfAvailable(this)
|
||||||
DynamicColors.applyToActivitiesIfAvailable(RevoltApplication.instance)
|
DynamicColors.applyToActivitiesIfAvailable(StoatApplication.instance)
|
||||||
@Suppress("DEPRECATION") // We are fixing a bug in the splash screen
|
@Suppress("DEPRECATION") // We are fixing a bug in the splash screen
|
||||||
window.statusBarColor = Color.Transparent.toArgb()
|
window.statusBarColor = Color.Transparent.toArgb()
|
||||||
}
|
}
|
||||||
|
|
@ -358,7 +358,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
window.statusBarColor = Color.Transparent.toArgb()
|
window.statusBarColor = Color.Transparent.toArgb()
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
|
||||||
RevoltAPI.hydrateFromPersistentCache()
|
StoatAPI.hydrateFromPersistentCache()
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
val windowSizeClass = calculateWindowSizeClass(this)
|
val windowSizeClass = calculateWindowSizeClass(this)
|
||||||
|
|
@ -426,10 +426,10 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val RevoltTweenInt: FiniteAnimationSpec<IntOffset> = tween(400, easing = EaseInOutExpo)
|
val StoatTweenInt: FiniteAnimationSpec<IntOffset> = tween(400, easing = EaseInOutExpo)
|
||||||
val RevoltTweenFloat: FiniteAnimationSpec<Float> = tween(400, easing = EaseInOutExpo)
|
val StoatTweenFloat: FiniteAnimationSpec<Float> = tween(400, easing = EaseInOutExpo)
|
||||||
val RevoltTweenDp: FiniteAnimationSpec<Dp> = tween(400, easing = EaseInOutExpo)
|
val StoatTweenDp: FiniteAnimationSpec<Dp> = tween(400, easing = EaseInOutExpo)
|
||||||
val RevoltTweenColour: FiniteAnimationSpec<Color> = tween(400, easing = EaseInOutExpo)
|
val StoatTweenColour: FiniteAnimationSpec<Color> = tween(400, easing = EaseInOutExpo)
|
||||||
|
|
||||||
val NavTweenInt: FiniteAnimationSpec<IntOffset> = tween(350, easing = EaseInOutExpo)
|
val NavTweenInt: FiniteAnimationSpec<IntOffset> = tween(350, easing = EaseInOutExpo)
|
||||||
val NavTweenFloat: FiniteAnimationSpec<Float> = tween(350, easing = EaseInOutExpo)
|
val NavTweenFloat: FiniteAnimationSpec<Float> = tween(350, easing = EaseInOutExpo)
|
||||||
|
|
@ -479,7 +479,7 @@ fun AppEntrypoint(
|
||||||
|
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
|
|
||||||
RevoltTheme(
|
StoatTheme(
|
||||||
requestedTheme = LoadedSettings.theme,
|
requestedTheme = LoadedSettings.theme,
|
||||||
colourOverrides = SyncedSettings.android.colourOverrides
|
colourOverrides = SyncedSettings.android.colourOverrides
|
||||||
) {
|
) {
|
||||||
|
|
@ -621,7 +621,7 @@ fun AppEntrypoint(
|
||||||
easing = EasingTokens.EmphasizedDecelerate
|
easing = EasingTokens.EmphasizedDecelerate
|
||||||
),
|
),
|
||||||
initialOffset = { it / 3 }
|
initialOffset = { it / 3 }
|
||||||
) + fadeIn(animationSpec = RevoltTweenFloat)
|
) + fadeIn(animationSpec = StoatTweenFloat)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
ChatRouterScreen(
|
ChatRouterScreen(
|
||||||
|
|
@ -655,7 +655,7 @@ fun AppEntrypoint(
|
||||||
easing = EasingTokens.EmphasizedDecelerate
|
easing = EasingTokens.EmphasizedDecelerate
|
||||||
),
|
),
|
||||||
initialOffset = { it / 3 }
|
initialOffset = { it / 3 }
|
||||||
) + fadeIn(animationSpec = RevoltTweenFloat) + scaleIn(
|
) + fadeIn(animationSpec = StoatTweenFloat) + scaleIn(
|
||||||
animationSpec = tween(
|
animationSpec = tween(
|
||||||
400,
|
400,
|
||||||
easing = EasingTokens.EmphasizedDecelerate
|
easing = EasingTokens.EmphasizedDecelerate
|
||||||
|
|
@ -677,7 +677,7 @@ fun AppEntrypoint(
|
||||||
easing = EasingTokens.EmphasizedDecelerate
|
easing = EasingTokens.EmphasizedDecelerate
|
||||||
),
|
),
|
||||||
initialOffset = { it }
|
initialOffset = { it }
|
||||||
) + fadeIn(animationSpec = RevoltTweenFloat)
|
) + fadeIn(animationSpec = StoatTweenFloat)
|
||||||
},
|
},
|
||||||
exitTransition = {
|
exitTransition = {
|
||||||
slideOutOfContainer(
|
slideOutOfContainer(
|
||||||
|
|
@ -687,7 +687,7 @@ fun AppEntrypoint(
|
||||||
easing = EasingTokens.EmphasizedDecelerate
|
easing = EasingTokens.EmphasizedDecelerate
|
||||||
),
|
),
|
||||||
targetOffset = { it }
|
targetOffset = { it }
|
||||||
) + fadeOut(animationSpec = RevoltTweenFloat)
|
) + fadeOut(animationSpec = StoatTweenFloat)
|
||||||
}
|
}
|
||||||
) { backStackEntry ->
|
) { backStackEntry ->
|
||||||
val channelId = backStackEntry.arguments?.getString("channelId") ?: ""
|
val channelId = backStackEntry.arguments?.getString("channelId") ?: ""
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.activities
|
package chat.stoat.activities
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
|
@ -50,25 +50,25 @@ import androidx.documentfile.provider.DocumentFile
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.internals.ChannelUtils
|
import chat.stoat.api.internals.ChannelUtils
|
||||||
import chat.revolt.api.routes.channel.sendMessage
|
import chat.stoat.api.routes.channel.sendMessage
|
||||||
import chat.revolt.api.routes.microservices.autumn.FileArgs
|
import chat.stoat.api.routes.microservices.autumn.FileArgs
|
||||||
import chat.revolt.api.routes.microservices.autumn.MAX_ATTACHMENTS_PER_MESSAGE
|
import chat.stoat.api.routes.microservices.autumn.MAX_ATTACHMENTS_PER_MESSAGE
|
||||||
import chat.revolt.api.routes.microservices.autumn.uploadToAutumn
|
import chat.stoat.api.routes.microservices.autumn.uploadToAutumn
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.stoat.api.schemas.ChannelType
|
||||||
import chat.revolt.api.settings.LoadedSettings
|
import chat.stoat.api.settings.LoadedSettings
|
||||||
import chat.revolt.api.settings.SyncedSettings
|
import chat.stoat.api.settings.SyncedSettings
|
||||||
import chat.revolt.composables.chat.MessageField
|
import chat.stoat.composables.chat.MessageField
|
||||||
import chat.revolt.composables.emoji.EmojiPicker
|
import chat.stoat.composables.emoji.EmojiPicker
|
||||||
import chat.revolt.composables.screens.chat.AttachmentManager
|
import chat.stoat.composables.screens.chat.AttachmentManager
|
||||||
import chat.revolt.composables.screens.chat.drawer.ChannelItem
|
import chat.stoat.composables.screens.chat.drawer.ChannelItem
|
||||||
import chat.revolt.composables.screens.chat.drawer.ChannelItemIconType
|
import chat.stoat.composables.screens.chat.drawer.ChannelItemIconType
|
||||||
import chat.revolt.composables.screens.chat.drawer.DMOrGroupItem
|
import chat.stoat.composables.screens.chat.drawer.DMOrGroupItem
|
||||||
import chat.revolt.persistence.KVStorage
|
import chat.stoat.persistence.KVStorage
|
||||||
import chat.revolt.screens.chat.views.channel.ChannelScreenActivePane
|
import chat.stoat.screens.chat.views.channel.ChannelScreenActivePane
|
||||||
import chat.revolt.ui.theme.RevoltTheme
|
import chat.stoat.ui.theme.StoatTheme
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import io.ktor.http.ContentType
|
import io.ktor.http.ContentType
|
||||||
|
|
@ -180,10 +180,10 @@ class ShareTargetScreenViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun initialiseAPI() {
|
suspend fun initialiseAPI() {
|
||||||
if (!RevoltAPI.isLoggedIn()) {
|
if (!StoatAPI.isLoggedIn()) {
|
||||||
val token = kvStorage.get("sessionToken") ?: return
|
val token = kvStorage.get("sessionToken") ?: return
|
||||||
RevoltAPI.loginAs(token)
|
StoatAPI.loginAs(token)
|
||||||
RevoltAPI.initialize()
|
StoatAPI.initialize()
|
||||||
}
|
}
|
||||||
apiIsReady = true
|
apiIsReady = true
|
||||||
}
|
}
|
||||||
|
|
@ -277,7 +277,7 @@ fun ShareTargetScreen(
|
||||||
var channelSearchContent by remember { mutableStateOf("") }
|
var channelSearchContent by remember { mutableStateOf("") }
|
||||||
var selectedChannel by rememberSaveable { mutableStateOf<String?>(null) }
|
var selectedChannel by rememberSaveable { mutableStateOf<String?>(null) }
|
||||||
|
|
||||||
RevoltTheme(
|
StoatTheme(
|
||||||
requestedTheme = LoadedSettings.theme,
|
requestedTheme = LoadedSettings.theme,
|
||||||
colourOverrides = SyncedSettings.android.colourOverrides
|
colourOverrides = SyncedSettings.android.colourOverrides
|
||||||
) {
|
) {
|
||||||
|
|
@ -326,7 +326,7 @@ fun ShareTargetScreen(
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
) {
|
) {
|
||||||
val filteredChannels = RevoltAPI.channelCache.values.asSequence().filter {
|
val filteredChannels = StoatAPI.channelCache.values.asSequence().filter {
|
||||||
it.name?.contains(
|
it.name?.contains(
|
||||||
channelSearchContent,
|
channelSearchContent,
|
||||||
ignoreCase = true
|
ignoreCase = true
|
||||||
|
|
@ -346,7 +346,7 @@ fun ShareTargetScreen(
|
||||||
ChannelType.Group, ChannelType.DirectMessage -> DMOrGroupItem(
|
ChannelType.Group, ChannelType.DirectMessage -> DMOrGroupItem(
|
||||||
channel = channel,
|
channel = channel,
|
||||||
partner = ChannelUtils.resolveDMPartner(channel)?.let { u ->
|
partner = ChannelUtils.resolveDMPartner(channel)?.let { u ->
|
||||||
RevoltAPI.userCache[u]
|
StoatAPI.userCache[u]
|
||||||
},
|
},
|
||||||
isCurrent = selectedChannel == channel.id,
|
isCurrent = selectedChannel == channel.id,
|
||||||
hasUnread = false,
|
hasUnread = false,
|
||||||
|
|
@ -421,9 +421,9 @@ fun ShareTargetScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
channelType = RevoltAPI.channelCache[selectedChannel]?.channelType
|
channelType = StoatAPI.channelCache[selectedChannel]?.channelType
|
||||||
?: ChannelType.TextChannel,
|
?: ChannelType.TextChannel,
|
||||||
channelName = RevoltAPI.channelCache[selectedChannel]?.name ?: "",
|
channelName = StoatAPI.channelCache[selectedChannel]?.name ?: "",
|
||||||
)
|
)
|
||||||
|
|
||||||
AnimatedVisibility(viewModel.activeBottomPane is ChannelScreenActivePane.EmojiPicker) {
|
AnimatedVisibility(viewModel.activeBottomPane is ChannelScreenActivePane.EmojiPicker) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.activities.media
|
package chat.stoat.activities.media
|
||||||
|
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
|
@ -40,14 +40,14 @@ import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.stoat.api.STOAT_FILES
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.schemas.AutumnResource
|
import chat.stoat.api.schemas.AutumnResource
|
||||||
import chat.revolt.api.settings.LoadedSettings
|
import chat.stoat.api.settings.LoadedSettings
|
||||||
import chat.revolt.api.settings.SyncedSettings
|
import chat.stoat.api.settings.SyncedSettings
|
||||||
import chat.revolt.providers.getAttachmentContentUri
|
import chat.stoat.providers.getAttachmentContentUri
|
||||||
import chat.revolt.ui.theme.RevoltTheme
|
import chat.stoat.ui.theme.StoatTheme
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.statement.readBytes
|
import io.ktor.client.statement.readBytes
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -85,7 +85,7 @@ class ImageViewActivity : ComponentActivity() {
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ImageViewScreen(resource: AutumnResource, onClose: () -> Unit = {}) {
|
fun ImageViewScreen(resource: AutumnResource, onClose: () -> Unit = {}) {
|
||||||
val resourceUrl = "$REVOLT_FILES/attachments/${resource.id}/${resource.filename}"
|
val resourceUrl = "$STOAT_FILES/attachments/${resource.id}/${resource.filename}"
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
|
@ -151,7 +151,7 @@ fun ImageViewScreen(resource: AutumnResource, onClose: () -> Unit = {}) {
|
||||||
)
|
)
|
||||||
}?.let { uri ->
|
}?.let { uri ->
|
||||||
context.contentResolver.openOutputStream(uri).use { stream ->
|
context.contentResolver.openOutputStream(uri).use { stream ->
|
||||||
val image = RevoltHttp.get(resourceUrl).readBytes()
|
val image = StoatHttp.get(resourceUrl).readBytes()
|
||||||
stream?.write(image)
|
stream?.write(image)
|
||||||
|
|
||||||
context.applicationContext.let {
|
context.applicationContext.let {
|
||||||
|
|
@ -182,7 +182,7 @@ fun ImageViewScreen(resource: AutumnResource, onClose: () -> Unit = {}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltTheme(
|
StoatTheme(
|
||||||
requestedTheme = LoadedSettings.theme,
|
requestedTheme = LoadedSettings.theme,
|
||||||
colourOverrides = SyncedSettings.android.colourOverrides
|
colourOverrides = SyncedSettings.android.colourOverrides
|
||||||
) {
|
) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.activities.media
|
package chat.stoat.activities.media
|
||||||
|
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
|
@ -18,12 +18,12 @@ import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.stoat.api.STOAT_FILES
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.schemas.AutumnResource
|
import chat.stoat.api.schemas.AutumnResource
|
||||||
import chat.revolt.databinding.ActivityVideoplayerBinding
|
import chat.stoat.databinding.ActivityVideoplayerBinding
|
||||||
import chat.revolt.providers.getAttachmentContentUri
|
import chat.stoat.providers.getAttachmentContentUri
|
||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
|
|
@ -54,7 +54,7 @@ class VideoViewActivity : FragmentActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val resourceUrl =
|
val resourceUrl =
|
||||||
"$REVOLT_FILES/attachments/${autumnResource.id}/${autumnResource.filename}"
|
"$STOAT_FILES/attachments/${autumnResource.id}/${autumnResource.filename}"
|
||||||
|
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
|
||||||
|
|
@ -195,7 +195,7 @@ class VideoViewActivity : FragmentActivity() {
|
||||||
)
|
)
|
||||||
}?.let { uri ->
|
}?.let { uri ->
|
||||||
this@VideoViewActivity.contentResolver.openOutputStream(uri).use { stream ->
|
this@VideoViewActivity.contentResolver.openOutputStream(uri).use { stream ->
|
||||||
val video = RevoltHttp.get(resourceUrl).readBytes()
|
val video = StoatHttp.get(resourceUrl).readBytes()
|
||||||
stream?.write(video)
|
stream?.write(video)
|
||||||
|
|
||||||
this@VideoViewActivity.applicationContext.let {
|
this@VideoViewActivity.applicationContext.let {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.activities.voice
|
package chat.stoat.activities.voice
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
|
@ -57,12 +57,12 @@ import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.IntOffset
|
import androidx.compose.ui.unit.IntOffset
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.composables.generic.Presence
|
import chat.stoat.composables.generic.Presence
|
||||||
import chat.revolt.composables.generic.RemoteImage
|
import chat.stoat.composables.generic.RemoteImage
|
||||||
import chat.revolt.composables.generic.presenceColour
|
import chat.stoat.composables.generic.presenceColour
|
||||||
import chat.revolt.ui.theme.RevoltTheme
|
import chat.stoat.ui.theme.StoatTheme
|
||||||
import chat.revolt.ui.theme.Theme
|
import chat.stoat.ui.theme.Theme
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
@ -80,8 +80,8 @@ class IncomingActivity : ComponentActivity() {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun IncomingCall() {
|
fun IncomingCall() {
|
||||||
RevoltTheme(
|
StoatTheme(
|
||||||
requestedTheme = if (isSystemInDarkTheme()) Theme.Revolt else Theme.Light
|
requestedTheme = if (isSystemInDarkTheme()) Theme.Default else Theme.Light
|
||||||
) {
|
) {
|
||||||
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onBackground) {
|
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onBackground) {
|
||||||
IncomingCallInner()
|
IncomingCallInner()
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
package chat.revolt.api
|
package chat.stoat.api
|
||||||
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.runtime.mutableStateMapOf
|
import androidx.compose.runtime.mutableStateMapOf
|
||||||
import chat.revolt.BuildConfig
|
import chat.stoat.BuildConfig
|
||||||
import chat.revolt.RevoltApplication
|
import chat.stoat.StoatApplication
|
||||||
import chat.revolt.api.RevoltAPI.initialize
|
import chat.stoat.api.StoatAPI.initialize
|
||||||
import chat.revolt.api.internals.Members
|
import chat.stoat.api.internals.Members
|
||||||
import chat.revolt.api.realtime.DisconnectionState
|
import chat.stoat.api.realtime.DisconnectionState
|
||||||
import chat.revolt.api.realtime.RealtimeSocket
|
import chat.stoat.api.realtime.RealtimeSocket
|
||||||
import chat.revolt.api.routes.user.fetchSelf
|
import chat.stoat.api.routes.user.fetchSelf
|
||||||
import chat.revolt.api.schemas.AutumnResource
|
import chat.stoat.api.schemas.AutumnResource
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.stoat.api.schemas.ChannelType
|
||||||
import chat.revolt.api.schemas.Emoji
|
import chat.stoat.api.schemas.Emoji
|
||||||
import chat.revolt.api.schemas.Message
|
import chat.stoat.api.schemas.Message
|
||||||
import chat.revolt.api.schemas.Server
|
import chat.stoat.api.schemas.Server
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
import chat.revolt.api.unreads.Unreads
|
import chat.stoat.api.unreads.Unreads
|
||||||
import chat.revolt.persistence.Database
|
import chat.stoat.persistence.Database
|
||||||
import chat.revolt.persistence.SqlStorage
|
import chat.stoat.persistence.SqlStorage
|
||||||
import com.chuckerteam.chucker.api.ChuckerCollector
|
import com.chuckerteam.chucker.api.ChuckerCollector
|
||||||
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
||||||
import com.chuckerteam.chucker.api.RetentionManager
|
import com.chuckerteam.chucker.api.RetentionManager
|
||||||
|
|
@ -51,49 +51,49 @@ import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.cbor.Cbor
|
import kotlinx.serialization.cbor.Cbor
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.net.SocketException
|
import java.net.SocketException
|
||||||
import chat.revolt.api.schemas.Channel as ChannelSchema
|
import chat.stoat.api.schemas.Channel as ChannelSchema
|
||||||
|
|
||||||
private const val USE_ALPHA_API = false
|
private const val USE_ALPHA_API = false
|
||||||
|
|
||||||
val REVOLT_BASE =
|
val STOAT_BASE =
|
||||||
if (USE_ALPHA_API) "https://alpha.revolt.chat/api" else "https://api.revolt.chat/0.8"
|
if (USE_ALPHA_API) "https://alpha.revolt.chat/api" else "https://api.stoat.chat/0.8"
|
||||||
const val REVOLT_SUPPORT = "https://support.revolt.chat"
|
const val STOAT_SUPPORT = "https://support.stoat.chat"
|
||||||
const val REVOLT_MARKETING = "https://revolt.chat"
|
const val STOAT_MARKETING = "https://stoat.chat"
|
||||||
val REVOLT_FILES =
|
val STOAT_FILES =
|
||||||
if (USE_ALPHA_API) "https://alpha.revolt.chat/autumn" else "https://cdn.revoltusercontent.com"
|
if (USE_ALPHA_API) "https://alpha.revolt.chat/autumn" else "https://cdn.stoatusercontent.com"
|
||||||
val REVOLT_JANUARY =
|
val STOAT_PROXY =
|
||||||
if (USE_ALPHA_API) "https://alpha.revolt.chat/january" else "https://jan.revolt.chat"
|
if (USE_ALPHA_API) "https://alpha.revolt.chat/january" else "https://proxy.stoatusercontent.com"
|
||||||
const val REVOLT_APP = "https://app.revolt.chat"
|
const val STOAT_WEB_APP = "https://stoat.chat/app"
|
||||||
const val REVOLT_INVITES = "https://rvlt.gg"
|
const val STOAT_INVITES = "https://stt.gg"
|
||||||
val REVOLT_WEBSOCKET =
|
val STOAT_WEBSOCKET =
|
||||||
if (USE_ALPHA_API) "wss://alpha.revolt.chat/ws" else "wss://ws.revolt.chat"
|
if (USE_ALPHA_API) "wss://alpha.revolt.chat/ws" else "wss://events.stoat.chat"
|
||||||
const val REVOLT_KJBOOK = "https://revoltchat.github.io/android"
|
const val STOAT_KJBOOK = "https://revoltchat.github.io/android"
|
||||||
|
|
||||||
fun String.api(): String {
|
fun String.api(): String {
|
||||||
return "$REVOLT_BASE$this"
|
return "$STOAT_BASE$this"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildUserAgent(accessMethod: String = "Ktor"): String {
|
fun buildUserAgent(accessMethod: String = "Ktor"): String {
|
||||||
return "$accessMethod RevoltAndroid/${BuildConfig.VERSION_NAME} " +
|
return "$accessMethod StoatForAndroid/${BuildConfig.VERSION_NAME} " +
|
||||||
"${BuildConfig.APPLICATION_ID} Android/${android.os.Build.VERSION.SDK_INT} " +
|
"${BuildConfig.APPLICATION_ID} Android/${android.os.Build.VERSION.SDK_INT} " +
|
||||||
"(${android.os.Build.MANUFACTURER} ${android.os.Build.DEVICE}) Kotlin/${KotlinVersion.CURRENT}"
|
"(${android.os.Build.MANUFACTURER} ${android.os.Build.DEVICE}) Kotlin/${KotlinVersion.CURRENT}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
val RevoltJson = Json {
|
val StoatJson = Json {
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
explicitNulls = false
|
explicitNulls = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
val RevoltCbor = Cbor {
|
val StoatCbor = Cbor {
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
}
|
}
|
||||||
|
|
||||||
val RevoltHttp = HttpClient(OkHttp) {
|
val StoatHttp = HttpClient(OkHttp) {
|
||||||
install(DefaultRequest)
|
install(DefaultRequest)
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
json(RevoltJson)
|
json(StoatJson)
|
||||||
}
|
}
|
||||||
|
|
||||||
install(WebSockets)
|
install(WebSockets)
|
||||||
|
|
@ -112,15 +112,15 @@ val RevoltHttp = HttpClient(OkHttp) {
|
||||||
install(Logging) { level = LogLevel.INFO }
|
install(Logging) { level = LogLevel.INFO }
|
||||||
|
|
||||||
val chuckerCollector = ChuckerCollector(
|
val chuckerCollector = ChuckerCollector(
|
||||||
context = RevoltApplication.instance,
|
context = StoatApplication.instance,
|
||||||
showNotification = true,
|
showNotification = true,
|
||||||
retentionPeriod = RetentionManager.Period.ONE_DAY
|
retentionPeriod = RetentionManager.Period.ONE_DAY
|
||||||
)
|
)
|
||||||
|
|
||||||
val chuckerInterceptor = ChuckerInterceptor.Builder(RevoltApplication.instance)
|
val chuckerInterceptor = ChuckerInterceptor.Builder(StoatApplication.instance)
|
||||||
.collector(chuckerCollector)
|
.collector(chuckerCollector)
|
||||||
.maxContentLength(250_000L)
|
.maxContentLength(250_000L)
|
||||||
.redactHeaders(RevoltAPI.TOKEN_HEADER_NAME)
|
.redactHeaders(StoatAPI.TOKEN_HEADER_NAME)
|
||||||
.alwaysReadResponseBody(true)
|
.alwaysReadResponseBody(true)
|
||||||
.createShortcut(false)
|
.createShortcut(false)
|
||||||
.build()
|
.build()
|
||||||
|
|
@ -129,8 +129,8 @@ val RevoltHttp = HttpClient(OkHttp) {
|
||||||
addInterceptor { chain ->
|
addInterceptor { chain ->
|
||||||
val request = chain.request().newBuilder()
|
val request = chain.request().newBuilder()
|
||||||
.apply {
|
.apply {
|
||||||
if (chain.request().headers[RevoltAPI.TOKEN_HEADER_NAME] == null) {
|
if (chain.request().headers[StoatAPI.TOKEN_HEADER_NAME] == null) {
|
||||||
header(RevoltAPI.TOKEN_HEADER_NAME, RevoltAPI.sessionToken)
|
header(StoatAPI.TOKEN_HEADER_NAME, StoatAPI.sessionToken)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
|
|
@ -140,14 +140,14 @@ val RevoltHttp = HttpClient(OkHttp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultRequest {
|
defaultRequest {
|
||||||
url(REVOLT_BASE)
|
url(STOAT_BASE)
|
||||||
header("User-Agent", buildUserAgent())
|
header("User-Agent", buildUserAgent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val mainHandler = Handler(Looper.getMainLooper())
|
val mainHandler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
object RevoltAPI {
|
object StoatAPI {
|
||||||
const val TOKEN_HEADER_NAME = "x-session-token"
|
const val TOKEN_HEADER_NAME = "x-session-token"
|
||||||
|
|
||||||
val userCache = mutableStateMapOf<String, User>()
|
val userCache = mutableStateMapOf<String, User>()
|
||||||
|
|
@ -369,7 +369,7 @@ object RevoltAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class RevoltError(val type: String)
|
data class StoatAPIError(val type: String)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class RateLimitResponse(@SerialName("retry_after") val retryAfter: Int) {
|
data class RateLimitResponse(@SerialName("retry_after") val retryAfter: Int) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.material3.LocalContentColor
|
import androidx.compose.material3.LocalContentColor
|
||||||
|
|
@ -9,7 +9,7 @@ import androidx.compose.ui.graphics.Brush.Companion.linearGradient
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
import chat.revolt.api.internals.colour.CSSColours
|
import chat.stoat.api.internals.colour.CSSColours
|
||||||
|
|
||||||
fun Brush.Companion.solidColor(colour: Color) = SolidColor(colour)
|
fun Brush.Companion.solidColor(colour: Color) = SolidColor(colour)
|
||||||
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.schemas.Channel
|
import chat.stoat.api.schemas.Channel
|
||||||
import chat.revolt.api.schemas.Server
|
import chat.stoat.api.schemas.Server
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
|
|
||||||
sealed class CategorisedChannelList {
|
sealed class CategorisedChannelList {
|
||||||
data class Channel(val channel: chat.revolt.api.schemas.Channel) : CategorisedChannelList()
|
data class Channel(val channel: chat.stoat.api.schemas.Channel) : CategorisedChannelList()
|
||||||
data class Category(val category: chat.revolt.api.schemas.Category) : CategorisedChannelList()
|
data class Category(val category: chat.stoat.api.schemas.Category) : CategorisedChannelList()
|
||||||
}
|
}
|
||||||
|
|
||||||
object ChannelUtils {
|
object ChannelUtils {
|
||||||
|
|
@ -19,7 +19,7 @@ object ChannelUtils {
|
||||||
*/
|
*/
|
||||||
fun resolveName(channel: Channel): String? {
|
fun resolveName(channel: Channel): String? {
|
||||||
return channel.name
|
return channel.name
|
||||||
?: RevoltAPI.userCache[channel.recipients?.first { u -> u != RevoltAPI.selfId }]?.let {
|
?: StoatAPI.userCache[channel.recipients?.first { u -> u != StoatAPI.selfId }]?.let {
|
||||||
User.resolveDefaultName(
|
User.resolveDefaultName(
|
||||||
it
|
it
|
||||||
)
|
)
|
||||||
|
|
@ -27,7 +27,7 @@ object ChannelUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resolveDMPartner(channel: Channel): String? {
|
fun resolveDMPartner(channel: Channel): String? {
|
||||||
return channel.recipients?.firstOrNull { u -> u != RevoltAPI.selfId }
|
return channel.recipients?.firstOrNull { u -> u != StoatAPI.selfId }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun categoriseServerFlat(server: Server): List<CategorisedChannelList> {
|
fun categoriseServerFlat(server: Server): List<CategorisedChannelList> {
|
||||||
|
|
@ -42,7 +42,7 @@ object ChannelUtils {
|
||||||
} ?: true
|
} ?: true
|
||||||
}
|
}
|
||||||
?.mapNotNull {
|
?.mapNotNull {
|
||||||
RevoltAPI.channelCache[it]?.let { it1 ->
|
StoatAPI.channelCache[it]?.let { it1 ->
|
||||||
CategorisedChannelList.Channel(it1)
|
CategorisedChannelList.Channel(it1)
|
||||||
}
|
}
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
|
|
@ -53,7 +53,7 @@ object ChannelUtils {
|
||||||
categories.forEach {
|
categories.forEach {
|
||||||
output.add(it)
|
output.add(it)
|
||||||
val channels = it.category.channels?.mapNotNull { c ->
|
val channels = it.category.channels?.mapNotNull { c ->
|
||||||
RevoltAPI.channelCache[c]?.let { it1 ->
|
StoatAPI.channelCache[c]?.let { it1 ->
|
||||||
CategorisedChannelList.Channel(it1)
|
CategorisedChannelList.Channel(it1)
|
||||||
}
|
}
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.internals.SpecialUsers.PLATFORM_MODERATION_USER
|
import chat.stoat.api.internals.SpecialUsers.PLATFORM_MODERATION_USER
|
||||||
import chat.revolt.api.schemas.Channel
|
import chat.stoat.api.schemas.Channel
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.stoat.api.schemas.ChannelType
|
||||||
|
|
||||||
object DirectMessages {
|
object DirectMessages {
|
||||||
fun unreadDMs(): List<Channel> {
|
fun unreadDMs(): List<Channel> {
|
||||||
return RevoltAPI.channelCache.values
|
return StoatAPI.channelCache.values
|
||||||
.filter {
|
.filter {
|
||||||
it.channelType in listOf(
|
it.channelType in listOf(
|
||||||
ChannelType.DirectMessage, ChannelType.Group
|
ChannelType.DirectMessage, ChannelType.Group
|
||||||
|
|
@ -15,7 +15,7 @@ object DirectMessages {
|
||||||
}
|
}
|
||||||
.filter {
|
.filter {
|
||||||
it.id?.let { id ->
|
it.id?.let { id ->
|
||||||
RevoltAPI.unreads.hasUnread(
|
StoatAPI.unreads.hasUnread(
|
||||||
id,
|
id,
|
||||||
it.lastMessageID!!,
|
it.lastMessageID!!,
|
||||||
serverId = null
|
serverId = null
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
|
|
@ -1,35 +1,35 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
|
|
||||||
object FriendRequests {
|
object FriendRequests {
|
||||||
fun getIncoming(): List<User> {
|
fun getIncoming(): List<User> {
|
||||||
return RevoltAPI.userCache.values.filter { user ->
|
return StoatAPI.userCache.values.filter { user ->
|
||||||
user.relationship == "Incoming"
|
user.relationship == "Incoming"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOutgoing(): List<User> {
|
fun getOutgoing(): List<User> {
|
||||||
return RevoltAPI.userCache.values.filter { user ->
|
return StoatAPI.userCache.values.filter { user ->
|
||||||
user.relationship == "Outgoing"
|
user.relationship == "Outgoing"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBlocked(): List<User> {
|
fun getBlocked(): List<User> {
|
||||||
return RevoltAPI.userCache.values.filter { user ->
|
return StoatAPI.userCache.values.filter { user ->
|
||||||
user.relationship == "Blocked"
|
user.relationship == "Blocked"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOnlineFriends(): List<User> {
|
fun getOnlineFriends(): List<User> {
|
||||||
return RevoltAPI.userCache.values.filter { user ->
|
return StoatAPI.userCache.values.filter { user ->
|
||||||
user.relationship == "Friend" && user.online == true
|
user.relationship == "Friend" && user.online == true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFriends(excludeOnline: Boolean = false): List<User> {
|
fun getFriends(excludeOnline: Boolean = false): List<User> {
|
||||||
return RevoltAPI.userCache.values.filter { user ->
|
return StoatAPI.userCache.values.filter { user ->
|
||||||
user.relationship == "Friend" && if (excludeOnline) user.online == false else true
|
user.relationship == "Friend" && if (excludeOnline) user.online == false else true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import chat.revolt.api.schemas.Member
|
import chat.stoat.api.schemas.Member
|
||||||
|
|
||||||
class Members {
|
class Members {
|
||||||
// memberCache (mapping of serverId to userId to member)
|
// memberCache (mapping of serverId to userId to member)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flags for messages that can be set to modify their behavior.
|
* Flags for messages that can be set to modify their behavior.
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
enum class PermissionBit(val value: Long) {
|
enum class PermissionBit(val value: Long) {
|
||||||
// * Generic permissions
|
// * Generic permissions
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.stoat.api.STOAT_FILES
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
|
|
||||||
object ResourceLocations {
|
object ResourceLocations {
|
||||||
fun userAvatarUrl(user: User?): String {
|
fun userAvatarUrl(user: User?): String {
|
||||||
if (user?.avatar != null) {
|
if (user?.avatar != null) {
|
||||||
return "$REVOLT_FILES/avatars/${user.avatar.id}"
|
return "$STOAT_FILES/avatars/${user.avatar.id}"
|
||||||
}
|
}
|
||||||
return "/users/${(user?.id ?: "").ifBlank { "0".repeat(26) }}/default_avatar".api()
|
return "/users/${(user?.id ?: "").ifBlank { "0".repeat(26) }}/default_avatar".api()
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.schemas.Channel
|
import chat.stoat.api.schemas.Channel
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.stoat.api.schemas.ChannelType
|
||||||
import chat.revolt.api.schemas.Member
|
import chat.stoat.api.schemas.Member
|
||||||
import chat.revolt.api.schemas.PermissionDescription
|
import chat.stoat.api.schemas.PermissionDescription
|
||||||
import chat.revolt.api.schemas.Role
|
import chat.stoat.api.schemas.Role
|
||||||
import chat.revolt.api.schemas.Server
|
import chat.stoat.api.schemas.Server
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
|
|
||||||
object Roles {
|
object Roles {
|
||||||
|
|
@ -27,8 +27,8 @@ object Roles {
|
||||||
withColour: Boolean = false,
|
withColour: Boolean = false,
|
||||||
hoisted: Boolean = false
|
hoisted: Boolean = false
|
||||||
): Role? {
|
): Role? {
|
||||||
val server = RevoltAPI.serverCache[serverId] ?: return null
|
val server = StoatAPI.serverCache[serverId] ?: return null
|
||||||
val member = RevoltAPI.members.getMember(serverId, userId) ?: return null
|
val member = StoatAPI.members.getMember(serverId, userId) ?: return null
|
||||||
|
|
||||||
val roles = member.roles?.map { roleId ->
|
val roles = member.roles?.map { roleId ->
|
||||||
server.roles?.get(roleId)
|
server.roles?.get(roleId)
|
||||||
|
|
@ -43,13 +43,13 @@ object Roles {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun inOrder(serverId: String, predicate: (Role) -> Boolean): List<Role> {
|
fun inOrder(serverId: String, predicate: (Role) -> Boolean): List<Role> {
|
||||||
val server = RevoltAPI.serverCache[serverId] ?: return emptyList()
|
val server = StoatAPI.serverCache[serverId] ?: return emptyList()
|
||||||
|
|
||||||
return server.roles?.values?.filter(predicate)?.sortedBy { it.rank } ?: emptyList()
|
return server.roles?.values?.filter(predicate)?.sortedBy { it.rank } ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun permissionFor(server: Server, member: Member): Long {
|
fun permissionFor(server: Server, member: Member): Long {
|
||||||
val user = RevoltAPI.userCache[member.id?.user] ?: return 0L
|
val user = StoatAPI.userCache[member.id?.user] ?: return 0L
|
||||||
|
|
||||||
if (user.privileged == true) return PermissionBit.GrantAllSafe.value
|
if (user.privileged == true) return PermissionBit.GrantAllSafe.value
|
||||||
if (server.owner == member.id?.user) return PermissionBit.GrantAllSafe.value
|
if (server.owner == member.id?.user) return PermissionBit.GrantAllSafe.value
|
||||||
|
|
@ -80,13 +80,13 @@ object Roles {
|
||||||
ChannelType.Group -> if (channel.owner == user?.id) PermissionBit.GrantAllSafe.value else BitDefaults.DirectMessages
|
ChannelType.Group -> if (channel.owner == user?.id) PermissionBit.GrantAllSafe.value else BitDefaults.DirectMessages
|
||||||
|
|
||||||
ChannelType.TextChannel, ChannelType.VoiceChannel -> {
|
ChannelType.TextChannel, ChannelType.VoiceChannel -> {
|
||||||
val server = RevoltAPI.serverCache[channel.server]
|
val server = StoatAPI.serverCache[channel.server]
|
||||||
// FIXME this is a stupid patch to prevent it from showing "no permission" on a channel on launch
|
// FIXME this is a stupid patch to prevent it from showing "no permission" on a channel on launch
|
||||||
?: return PermissionBit.GrantAllSafe.value
|
?: return PermissionBit.GrantAllSafe.value
|
||||||
|
|
||||||
if (server.owner == user?.id) return PermissionBit.GrantAllSafe.value
|
if (server.owner == user?.id) return PermissionBit.GrantAllSafe.value
|
||||||
|
|
||||||
val chMember = member ?: RevoltAPI.members.getMember(
|
val chMember = member ?: StoatAPI.members.getMember(
|
||||||
server.id ?: return 0L,
|
server.id ?: return 0L,
|
||||||
user?.id ?: return 0L
|
user?.id ?: return 0L
|
||||||
) ?: return 0L
|
) ?: return 0L
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.RuntimeShader
|
import android.graphics.RuntimeShader
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import android.graphics.LinearGradient
|
import android.graphics.LinearGradient
|
||||||
import android.graphics.Shader
|
import android.graphics.Shader
|
||||||
|
|
@ -6,7 +6,7 @@ import android.util.Log
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
import chat.revolt.api.internals.colour.CSSColours
|
import chat.stoat.api.internals.colour.CSSColours
|
||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
import com.google.android.material.elevation.SurfaceColors
|
import com.google.android.material.elevation.SurfaceColors
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import kotlin.experimental.and
|
import kotlin.experimental.and
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
package chat.revolt.api.internals
|
package chat.stoat.api.internals
|
||||||
|
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import chat.revolt.api.RevoltCbor
|
import chat.stoat.api.STOAT_MARKETING
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.StoatCbor
|
||||||
|
import chat.stoat.api.schemas.User
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlin.io.encoding.Base64
|
import kotlin.io.encoding.Base64
|
||||||
|
|
@ -21,8 +22,8 @@ data class UserQRContents(
|
||||||
object UserQR {
|
object UserQR {
|
||||||
@OptIn(ExperimentalSerializationApi::class, ExperimentalEncodingApi::class)
|
@OptIn(ExperimentalSerializationApi::class, ExperimentalEncodingApi::class)
|
||||||
fun contents(user: User): String {
|
fun contents(user: User): String {
|
||||||
return "https://revolt.chat/qr?" + Base64.encode(
|
return "$STOAT_MARKETING/qr?" + Base64.encode(
|
||||||
RevoltCbor.encodeToByteArray(
|
StoatCbor.encodeToByteArray(
|
||||||
UserQRContents.serializer(),
|
UserQRContents.serializer(),
|
||||||
UserQRContents(
|
UserQRContents(
|
||||||
format = "rqr\$user\$0",
|
format = "rqr\$user\$0",
|
||||||
|
|
@ -45,7 +46,7 @@ object UserQR {
|
||||||
val uri = uriString.toUri()
|
val uri = uriString.toUri()
|
||||||
val base64 = uri.query ?: return null
|
val base64 = uri.query ?: return null
|
||||||
val decodedBytes = Base64.decode(base64)
|
val decodedBytes = Base64.decode(base64)
|
||||||
RevoltCbor.decodeFromByteArray(UserQRContents.serializer(), decodedBytes)
|
StoatCbor.decodeFromByteArray(UserQRContents.serializer(), decodedBytes)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.internals.colour
|
package chat.stoat.api.internals.colour
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
|
|
@ -1,49 +1,49 @@
|
||||||
package chat.revolt.api.realtime
|
package chat.stoat.api.realtime
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import chat.revolt.RevoltApplication
|
import chat.stoat.StoatApplication
|
||||||
import chat.revolt.api.REVOLT_WEBSOCKET
|
import chat.stoat.api.STOAT_WEBSOCKET
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.realtime.frames.receivable.AnyFrame
|
import chat.stoat.api.realtime.frames.receivable.AnyFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.BulkFrame
|
import chat.stoat.api.realtime.frames.receivable.BulkFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ChannelAckFrame
|
import chat.stoat.api.realtime.frames.receivable.ChannelAckFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ChannelDeleteFrame
|
import chat.stoat.api.realtime.frames.receivable.ChannelDeleteFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ChannelStartTypingFrame
|
import chat.stoat.api.realtime.frames.receivable.ChannelStartTypingFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ChannelStopTypingFrame
|
import chat.stoat.api.realtime.frames.receivable.ChannelStopTypingFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ChannelUpdateFrame
|
import chat.stoat.api.realtime.frames.receivable.ChannelUpdateFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.MessageAppendFrame
|
import chat.stoat.api.realtime.frames.receivable.MessageAppendFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.MessageDeleteFrame
|
import chat.stoat.api.realtime.frames.receivable.MessageDeleteFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.MessageFrame
|
import chat.stoat.api.realtime.frames.receivable.MessageFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.MessageReactFrame
|
import chat.stoat.api.realtime.frames.receivable.MessageReactFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.MessageUpdateFrame
|
import chat.stoat.api.realtime.frames.receivable.MessageUpdateFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.PongFrame
|
import chat.stoat.api.realtime.frames.receivable.PongFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ReadyFrame
|
import chat.stoat.api.realtime.frames.receivable.ReadyFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ServerCreateFrame
|
import chat.stoat.api.realtime.frames.receivable.ServerCreateFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ServerDeleteFrame
|
import chat.stoat.api.realtime.frames.receivable.ServerDeleteFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ServerMemberJoinFrame
|
import chat.stoat.api.realtime.frames.receivable.ServerMemberJoinFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ServerMemberLeaveFrame
|
import chat.stoat.api.realtime.frames.receivable.ServerMemberLeaveFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ServerMemberUpdateFrame
|
import chat.stoat.api.realtime.frames.receivable.ServerMemberUpdateFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ServerRoleDeleteFrame
|
import chat.stoat.api.realtime.frames.receivable.ServerRoleDeleteFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ServerRoleUpdateFrame
|
import chat.stoat.api.realtime.frames.receivable.ServerRoleUpdateFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.ServerUpdateFrame
|
import chat.stoat.api.realtime.frames.receivable.ServerUpdateFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.UserRelationshipFrame
|
import chat.stoat.api.realtime.frames.receivable.UserRelationshipFrame
|
||||||
import chat.revolt.api.realtime.frames.receivable.UserUpdateFrame
|
import chat.stoat.api.realtime.frames.receivable.UserUpdateFrame
|
||||||
import chat.revolt.api.realtime.frames.sendable.AuthorizationFrame
|
import chat.stoat.api.realtime.frames.sendable.AuthorizationFrame
|
||||||
import chat.revolt.api.realtime.frames.sendable.BeginTypingFrame
|
import chat.stoat.api.realtime.frames.sendable.BeginTypingFrame
|
||||||
import chat.revolt.api.realtime.frames.sendable.EndTypingFrame
|
import chat.stoat.api.realtime.frames.sendable.EndTypingFrame
|
||||||
import chat.revolt.api.realtime.frames.sendable.PingFrame
|
import chat.stoat.api.realtime.frames.sendable.PingFrame
|
||||||
import chat.revolt.api.routes.server.fetchMember
|
import chat.stoat.api.routes.server.fetchMember
|
||||||
import chat.revolt.api.schemas.Channel
|
import chat.stoat.api.schemas.Channel
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.stoat.api.schemas.ChannelType
|
||||||
import chat.revolt.api.schemas.Role
|
import chat.stoat.api.schemas.Role
|
||||||
import chat.revolt.api.settings.LoadedSettings
|
import chat.stoat.api.settings.LoadedSettings
|
||||||
import chat.revolt.api.settings.SyncedSettings
|
import chat.stoat.api.settings.SyncedSettings
|
||||||
import chat.revolt.c2dm.ChannelRegistrator
|
import chat.stoat.c2dm.ChannelRegistrator
|
||||||
import chat.revolt.persistence.Database
|
import chat.stoat.persistence.Database
|
||||||
import chat.revolt.persistence.SqlStorage
|
import chat.stoat.persistence.SqlStorage
|
||||||
import io.ktor.client.plugins.websocket.ws
|
import io.ktor.client.plugins.websocket.ws
|
||||||
import io.ktor.websocket.CloseReason
|
import io.ktor.websocket.CloseReason
|
||||||
import io.ktor.websocket.Frame
|
import io.ktor.websocket.Frame
|
||||||
|
|
@ -70,7 +70,7 @@ object RealtimeSocket {
|
||||||
var socket: WebSocketSession? = null
|
var socket: WebSocketSession? = null
|
||||||
|
|
||||||
private val channelRegistrator: ChannelRegistrator
|
private val channelRegistrator: ChannelRegistrator
|
||||||
get() = ChannelRegistrator(RevoltApplication.instance)
|
get() = ChannelRegistrator(StoatApplication.instance)
|
||||||
|
|
||||||
private var _disconnectionState = mutableStateOf(DisconnectionState.Reconnecting)
|
private var _disconnectionState = mutableStateOf(DisconnectionState.Reconnecting)
|
||||||
val disconnectionState: DisconnectionState
|
val disconnectionState: DisconnectionState
|
||||||
|
|
@ -88,7 +88,7 @@ object RealtimeSocket {
|
||||||
|
|
||||||
socket?.close(CloseReason(CloseReason.Codes.NORMAL, "Reconnecting to websocket."))
|
socket?.close(CloseReason(CloseReason.Codes.NORMAL, "Reconnecting to websocket."))
|
||||||
|
|
||||||
RevoltHttp.ws(REVOLT_WEBSOCKET) {
|
StoatHttp.ws(STOAT_WEBSOCKET) {
|
||||||
socket = this
|
socket = this
|
||||||
|
|
||||||
Log.d("RealtimeSocket", "Connected to websocket.")
|
Log.d("RealtimeSocket", "Connected to websocket.")
|
||||||
|
|
@ -98,7 +98,7 @@ object RealtimeSocket {
|
||||||
// Send authorization frame
|
// Send authorization frame
|
||||||
val authFrame = AuthorizationFrame("Authenticate", token)
|
val authFrame = AuthorizationFrame("Authenticate", token)
|
||||||
val authFrameString =
|
val authFrameString =
|
||||||
RevoltJson.encodeToString(AuthorizationFrame.serializer(), authFrame)
|
StoatJson.encodeToString(AuthorizationFrame.serializer(), authFrame)
|
||||||
|
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
|
|
@ -109,13 +109,13 @@ object RealtimeSocket {
|
||||||
)
|
)
|
||||||
}"
|
}"
|
||||||
)
|
)
|
||||||
send(RevoltJson.encodeToString(AuthorizationFrame.serializer(), authFrame))
|
send(StoatJson.encodeToString(AuthorizationFrame.serializer(), authFrame))
|
||||||
|
|
||||||
incoming.consumeEach { frame ->
|
incoming.consumeEach { frame ->
|
||||||
if (frame is Frame.Text) {
|
if (frame is Frame.Text) {
|
||||||
val frameString = frame.readText()
|
val frameString = frame.readText()
|
||||||
val frameType =
|
val frameType =
|
||||||
RevoltJson.decodeFromString(AnyFrame.serializer(), frameString).type
|
StoatJson.decodeFromString(AnyFrame.serializer(), frameString).type
|
||||||
|
|
||||||
handleFrame(frameType, frameString)
|
handleFrame(frameType, frameString)
|
||||||
}
|
}
|
||||||
|
|
@ -127,29 +127,29 @@ object RealtimeSocket {
|
||||||
if (disconnectionState != DisconnectionState.Connected) return
|
if (disconnectionState != DisconnectionState.Connected) return
|
||||||
|
|
||||||
val pingPacket = PingFrame("Ping", System.currentTimeMillis())
|
val pingPacket = PingFrame("Ping", System.currentTimeMillis())
|
||||||
socket?.send(RevoltJson.encodeToString(PingFrame.serializer(), pingPacket))
|
socket?.send(StoatJson.encodeToString(PingFrame.serializer(), pingPacket))
|
||||||
Log.d("RealtimeSocket", "Sent ping frame with ${pingPacket.data}")
|
Log.d("RealtimeSocket", "Sent ping frame with ${pingPacket.data}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun handleFrame(type: String, rawFrame: String) {
|
private suspend fun handleFrame(type: String, rawFrame: String) {
|
||||||
when (type) {
|
when (type) {
|
||||||
"Pong" -> {
|
"Pong" -> {
|
||||||
val pongFrame = RevoltJson.decodeFromString(PongFrame.serializer(), rawFrame)
|
val pongFrame = StoatJson.decodeFromString(PongFrame.serializer(), rawFrame)
|
||||||
Log.d("RealtimeSocket", "Received pong frame for ${pongFrame.data}")
|
Log.d("RealtimeSocket", "Received pong frame for ${pongFrame.data}")
|
||||||
}
|
}
|
||||||
|
|
||||||
"Bulk" -> {
|
"Bulk" -> {
|
||||||
val bulkFrame = RevoltJson.decodeFromString(BulkFrame.serializer(), rawFrame)
|
val bulkFrame = StoatJson.decodeFromString(BulkFrame.serializer(), rawFrame)
|
||||||
Log.d("RealtimeSocket", "Received bulk frame with ${bulkFrame.v.size} sub-frames.")
|
Log.d("RealtimeSocket", "Received bulk frame with ${bulkFrame.v.size} sub-frames.")
|
||||||
bulkFrame.v.forEach { subFrame ->
|
bulkFrame.v.forEach { subFrame ->
|
||||||
val subFrameType =
|
val subFrameType =
|
||||||
RevoltJson.decodeFromString(AnyFrame.serializer(), subFrame.toString()).type
|
StoatJson.decodeFromString(AnyFrame.serializer(), subFrame.toString()).type
|
||||||
handleFrame(subFrameType, subFrame.toString())
|
handleFrame(subFrameType, subFrame.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"Ready" -> {
|
"Ready" -> {
|
||||||
val readyFrame = RevoltJson.decodeFromString(ReadyFrame.serializer(), rawFrame)
|
val readyFrame = StoatJson.decodeFromString(ReadyFrame.serializer(), rawFrame)
|
||||||
|
|
||||||
logcat {
|
logcat {
|
||||||
"Received ready frame with ${readyFrame.users.size} users, " +
|
"Received ready frame with ${readyFrame.users.size} users, " +
|
||||||
|
|
@ -161,11 +161,11 @@ object RealtimeSocket {
|
||||||
|
|
||||||
Log.d("RealtimeSocket", "Adding users to cache.")
|
Log.d("RealtimeSocket", "Adding users to cache.")
|
||||||
val userMap = readyFrame.users.associateBy { it.id!! }
|
val userMap = readyFrame.users.associateBy { it.id!! }
|
||||||
RevoltAPI.userCache.putAll(userMap)
|
StoatAPI.userCache.putAll(userMap)
|
||||||
|
|
||||||
Log.d("RealtimeSocket", "Adding servers to cache.")
|
Log.d("RealtimeSocket", "Adding servers to cache.")
|
||||||
val serverMap = readyFrame.servers.associateBy { it.id!! }
|
val serverMap = readyFrame.servers.associateBy { it.id!! }
|
||||||
RevoltAPI.serverCache.putAll(serverMap)
|
StoatAPI.serverCache.putAll(serverMap)
|
||||||
|
|
||||||
// Cache servers in persistent local database
|
// Cache servers in persistent local database
|
||||||
readyFrame.servers.map {
|
readyFrame.servers.map {
|
||||||
|
|
@ -196,12 +196,12 @@ object RealtimeSocket {
|
||||||
"Deleted server $it from local database due to not being in ready frame."
|
"Deleted server $it from local database due to not being in ready frame."
|
||||||
)
|
)
|
||||||
// Conversely, remove the server from the API state
|
// Conversely, remove the server from the API state
|
||||||
RevoltAPI.serverCache.remove(it)
|
StoatAPI.serverCache.remove(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d("RealtimeSocket", "Adding channels to cache.")
|
Log.d("RealtimeSocket", "Adding channels to cache.")
|
||||||
val channelMap = readyFrame.channels.associateBy { it.id!! }
|
val channelMap = readyFrame.channels.associateBy { it.id!! }
|
||||||
RevoltAPI.channelCache.putAll(channelMap)
|
StoatAPI.channelCache.putAll(channelMap)
|
||||||
|
|
||||||
// Cache channels in persistent local database
|
// Cache channels in persistent local database
|
||||||
readyFrame.channels.map {
|
readyFrame.channels.map {
|
||||||
|
|
@ -216,7 +216,7 @@ object RealtimeSocket {
|
||||||
it.name,
|
it.name,
|
||||||
it.owner,
|
it.owner,
|
||||||
it.description,
|
it.description,
|
||||||
if (it.channelType == ChannelType.DirectMessage) it.recipients?.firstOrNull { u -> u != RevoltAPI.selfId } else null,
|
if (it.channelType == ChannelType.DirectMessage) it.recipients?.firstOrNull { u -> u != StoatAPI.selfId } else null,
|
||||||
it.icon?.id,
|
it.icon?.id,
|
||||||
it.lastMessageID,
|
it.lastMessageID,
|
||||||
if (it.active == true) 1L else 0L,
|
if (it.active == true) 1L else 0L,
|
||||||
|
|
@ -237,21 +237,21 @@ object RealtimeSocket {
|
||||||
"Deleted channel $it from local database due to not being in ready frame."
|
"Deleted channel $it from local database due to not being in ready frame."
|
||||||
)
|
)
|
||||||
// Conversely, remove the channel from the API state
|
// Conversely, remove the channel from the API state
|
||||||
RevoltAPI.channelCache.remove(it)
|
StoatAPI.channelCache.remove(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d("RealtimeSocket", "Adding emojis to cache.")
|
Log.d("RealtimeSocket", "Adding emojis to cache.")
|
||||||
val emojiMap = readyFrame.emojis.associateBy { it.id!! }
|
val emojiMap = readyFrame.emojis.associateBy { it.id!! }
|
||||||
RevoltAPI.emojiCache.putAll(emojiMap)
|
StoatAPI.emojiCache.putAll(emojiMap)
|
||||||
|
|
||||||
Log.d("RealtimeSocket", "Registering push notification channels.")
|
Log.d("RealtimeSocket", "Registering push notification channels.")
|
||||||
channelRegistrator.register()
|
channelRegistrator.register()
|
||||||
|
|
||||||
RevoltAPI.closeHydration()
|
StoatAPI.closeHydration()
|
||||||
}
|
}
|
||||||
|
|
||||||
"Message" -> {
|
"Message" -> {
|
||||||
val messageFrame = RevoltJson.decodeFromString(MessageFrame.serializer(), rawFrame)
|
val messageFrame = StoatJson.decodeFromString(MessageFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received message frame for ${messageFrame.id} in channel ${messageFrame.channel}."
|
"Received message frame for ${messageFrame.id} in channel ${messageFrame.channel}."
|
||||||
|
|
@ -262,30 +262,30 @@ object RealtimeSocket {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.messageCache[messageFrame.id] = messageFrame
|
StoatAPI.messageCache[messageFrame.id] = messageFrame
|
||||||
|
|
||||||
messageFrame.channel?.let {
|
messageFrame.channel?.let {
|
||||||
if (RevoltAPI.channelCache[it] == null) {
|
if (StoatAPI.channelCache[it] == null) {
|
||||||
Log.d("RealtimeSocket", "Channel $it not found in cache. Ignoring.")
|
Log.d("RealtimeSocket", "Channel $it not found in cache. Ignoring.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.channelCache[it] =
|
StoatAPI.channelCache[it] =
|
||||||
RevoltAPI.channelCache[it]!!.copy(lastMessageID = messageFrame.id)
|
StoatAPI.channelCache[it]!!.copy(lastMessageID = messageFrame.id)
|
||||||
|
|
||||||
RevoltAPI.wsFrameChannel.send(messageFrame)
|
StoatAPI.wsFrameChannel.send(messageFrame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"MessageAppend" -> {
|
"MessageAppend" -> {
|
||||||
val messageAppendFrame =
|
val messageAppendFrame =
|
||||||
RevoltJson.decodeFromString(MessageAppendFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(MessageAppendFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received message append frame for ${messageAppendFrame.id} in channel ${messageAppendFrame.channel}."
|
"Received message append frame for ${messageAppendFrame.id} in channel ${messageAppendFrame.channel}."
|
||||||
)
|
)
|
||||||
|
|
||||||
var message = RevoltAPI.messageCache[messageAppendFrame.id]
|
var message = StoatAPI.messageCache[messageAppendFrame.id]
|
||||||
|
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
Log.d(
|
Log.d(
|
||||||
|
|
@ -299,20 +299,20 @@ object RealtimeSocket {
|
||||||
message = message!!.copy(embeds = message!!.embeds?.plus(it) ?: it)
|
message = message!!.copy(embeds = message!!.embeds?.plus(it) ?: it)
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.messageCache[messageAppendFrame.id] = message!!
|
StoatAPI.messageCache[messageAppendFrame.id] = message!!
|
||||||
|
|
||||||
RevoltAPI.wsFrameChannel.send(messageAppendFrame)
|
StoatAPI.wsFrameChannel.send(messageAppendFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
"MessageUpdate" -> {
|
"MessageUpdate" -> {
|
||||||
val messageUpdateFrame =
|
val messageUpdateFrame =
|
||||||
RevoltJson.decodeFromString(MessageUpdateFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(MessageUpdateFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received message update frame for ${messageUpdateFrame.id} in channel ${messageUpdateFrame.channel}."
|
"Received message update frame for ${messageUpdateFrame.id} in channel ${messageUpdateFrame.channel}."
|
||||||
)
|
)
|
||||||
|
|
||||||
val oldMessage = RevoltAPI.messageCache[messageUpdateFrame.id]
|
val oldMessage = StoatAPI.messageCache[messageUpdateFrame.id]
|
||||||
if (oldMessage == null) {
|
if (oldMessage == null) {
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
|
|
@ -324,7 +324,7 @@ object RealtimeSocket {
|
||||||
val rawMessage: MessageFrame
|
val rawMessage: MessageFrame
|
||||||
try {
|
try {
|
||||||
rawMessage =
|
rawMessage =
|
||||||
RevoltJson.decodeFromJsonElement(
|
StoatJson.decodeFromJsonElement(
|
||||||
MessageFrame.serializer(),
|
MessageFrame.serializer(),
|
||||||
messageUpdateFrame.data
|
messageUpdateFrame.data
|
||||||
)
|
)
|
||||||
|
|
@ -338,28 +338,28 @@ object RealtimeSocket {
|
||||||
"Merging message ${messageUpdateFrame.id} with updated partial."
|
"Merging message ${messageUpdateFrame.id} with updated partial."
|
||||||
)
|
)
|
||||||
|
|
||||||
RevoltAPI.messageCache[messageUpdateFrame.id] =
|
StoatAPI.messageCache[messageUpdateFrame.id] =
|
||||||
oldMessage.mergeWithPartial(rawMessage)
|
oldMessage.mergeWithPartial(rawMessage)
|
||||||
|
|
||||||
messageUpdateFrame.channel.let {
|
messageUpdateFrame.channel.let {
|
||||||
if (RevoltAPI.channelCache[it] == null) {
|
if (StoatAPI.channelCache[it] == null) {
|
||||||
Log.d("RealtimeSocket", "Channel $it not found in cache. Ignoring.")
|
Log.d("RealtimeSocket", "Channel $it not found in cache. Ignoring.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.wsFrameChannel.send(messageUpdateFrame)
|
StoatAPI.wsFrameChannel.send(messageUpdateFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
"MessageDelete" -> {
|
"MessageDelete" -> {
|
||||||
val messageDeleteFrame =
|
val messageDeleteFrame =
|
||||||
RevoltJson.decodeFromString(MessageDeleteFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(MessageDeleteFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received message react frame for ${messageDeleteFrame.id}."
|
"Received message react frame for ${messageDeleteFrame.id}."
|
||||||
)
|
)
|
||||||
|
|
||||||
val message = RevoltAPI.messageCache[messageDeleteFrame.id]
|
val message = StoatAPI.messageCache[messageDeleteFrame.id]
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
|
|
@ -368,19 +368,19 @@ object RealtimeSocket {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.messageCache.remove(messageDeleteFrame.id)
|
StoatAPI.messageCache.remove(messageDeleteFrame.id)
|
||||||
RevoltAPI.wsFrameChannel.send(messageDeleteFrame)
|
StoatAPI.wsFrameChannel.send(messageDeleteFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
"MessageReact" -> {
|
"MessageReact" -> {
|
||||||
val messageReactFrame =
|
val messageReactFrame =
|
||||||
RevoltJson.decodeFromString(MessageReactFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(MessageReactFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received message react frame for ${messageReactFrame.id}."
|
"Received message react frame for ${messageReactFrame.id}."
|
||||||
)
|
)
|
||||||
|
|
||||||
val oldMessage = RevoltAPI.messageCache[messageReactFrame.id]
|
val oldMessage = StoatAPI.messageCache[messageReactFrame.id]
|
||||||
if (oldMessage == null) {
|
if (oldMessage == null) {
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
|
|
@ -395,21 +395,21 @@ object RealtimeSocket {
|
||||||
forEmoji.add(messageReactFrame.user_id)
|
forEmoji.add(messageReactFrame.user_id)
|
||||||
reactions[messageReactFrame.emoji_id] = forEmoji
|
reactions[messageReactFrame.emoji_id] = forEmoji
|
||||||
|
|
||||||
RevoltAPI.messageCache[messageReactFrame.id] =
|
StoatAPI.messageCache[messageReactFrame.id] =
|
||||||
oldMessage.copy(reactions = reactions)
|
oldMessage.copy(reactions = reactions)
|
||||||
|
|
||||||
RevoltAPI.wsFrameChannel.send(messageReactFrame)
|
StoatAPI.wsFrameChannel.send(messageReactFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
"MessageUnreact" -> {
|
"MessageUnreact" -> {
|
||||||
val messageUnreactFrame =
|
val messageUnreactFrame =
|
||||||
RevoltJson.decodeFromString(MessageReactFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(MessageReactFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received message unreact frame for ${messageUnreactFrame.id}."
|
"Received message unreact frame for ${messageUnreactFrame.id}."
|
||||||
)
|
)
|
||||||
|
|
||||||
val oldMessage = RevoltAPI.messageCache[messageUnreactFrame.id]
|
val oldMessage = StoatAPI.messageCache[messageUnreactFrame.id]
|
||||||
if (oldMessage == null) {
|
if (oldMessage == null) {
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
|
|
@ -429,38 +429,38 @@ object RealtimeSocket {
|
||||||
reactions[messageUnreactFrame.emoji_id] = forEmoji
|
reactions[messageUnreactFrame.emoji_id] = forEmoji
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.messageCache[messageUnreactFrame.id] =
|
StoatAPI.messageCache[messageUnreactFrame.id] =
|
||||||
oldMessage.copy(reactions = reactions)
|
oldMessage.copy(reactions = reactions)
|
||||||
|
|
||||||
RevoltAPI.wsFrameChannel.send(messageUnreactFrame)
|
StoatAPI.wsFrameChannel.send(messageUnreactFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
"UserUpdate" -> {
|
"UserUpdate" -> {
|
||||||
val userUpdateFrame =
|
val userUpdateFrame =
|
||||||
RevoltJson.decodeFromString(UserUpdateFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(UserUpdateFrame.serializer(), rawFrame)
|
||||||
|
|
||||||
val existing = RevoltAPI.userCache[userUpdateFrame.id]
|
val existing = StoatAPI.userCache[userUpdateFrame.id]
|
||||||
?: return // if we don't have the user no point in updating it
|
?: return // if we don't have the user no point in updating it
|
||||||
|
|
||||||
if (userUpdateFrame.clear != null) {
|
if (userUpdateFrame.clear != null) {
|
||||||
if (userUpdateFrame.clear.contains("Avatar")) {
|
if (userUpdateFrame.clear.contains("Avatar")) {
|
||||||
RevoltAPI.userCache[userUpdateFrame.id] =
|
StoatAPI.userCache[userUpdateFrame.id] =
|
||||||
existing.copy(avatar = null)
|
existing.copy(avatar = null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.userCache[userUpdateFrame.id] =
|
StoatAPI.userCache[userUpdateFrame.id] =
|
||||||
existing.mergeWithPartial(userUpdateFrame.data)
|
existing.mergeWithPartial(userUpdateFrame.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
"UserRelationship" -> {
|
"UserRelationship" -> {
|
||||||
val userRelationshipFrame =
|
val userRelationshipFrame =
|
||||||
RevoltJson.decodeFromString(UserRelationshipFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(UserRelationshipFrame.serializer(), rawFrame)
|
||||||
|
|
||||||
val existing = RevoltAPI.userCache[userRelationshipFrame.user.id]
|
val existing = StoatAPI.userCache[userRelationshipFrame.user.id]
|
||||||
|
|
||||||
if (existing == null && userRelationshipFrame.user.id != null) {
|
if (existing == null && userRelationshipFrame.user.id != null) {
|
||||||
RevoltAPI.userCache[userRelationshipFrame.user.id] =
|
StoatAPI.userCache[userRelationshipFrame.user.id] =
|
||||||
userRelationshipFrame.user.copy(
|
userRelationshipFrame.user.copy(
|
||||||
relationship = userRelationshipFrame.status ?: "None"
|
relationship = userRelationshipFrame.status ?: "None"
|
||||||
)
|
)
|
||||||
|
|
@ -468,7 +468,7 @@ object RealtimeSocket {
|
||||||
val merged = existing.mergeWithPartial(userRelationshipFrame.user).copy(
|
val merged = existing.mergeWithPartial(userRelationshipFrame.user).copy(
|
||||||
relationship = userRelationshipFrame.status ?: "None"
|
relationship = userRelationshipFrame.status ?: "None"
|
||||||
)
|
)
|
||||||
RevoltAPI.userCache[userRelationshipFrame.user.id] = merged
|
StoatAPI.userCache[userRelationshipFrame.user.id] = merged
|
||||||
} else {
|
} else {
|
||||||
Log.w("RealtimeSocket", "Invalid UserRelationship frame: $rawFrame")
|
Log.w("RealtimeSocket", "Invalid UserRelationship frame: $rawFrame")
|
||||||
}
|
}
|
||||||
|
|
@ -476,13 +476,13 @@ object RealtimeSocket {
|
||||||
|
|
||||||
"ChannelUpdate" -> {
|
"ChannelUpdate" -> {
|
||||||
val channelUpdateFrame =
|
val channelUpdateFrame =
|
||||||
RevoltJson.decodeFromString(ChannelUpdateFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ChannelUpdateFrame.serializer(), rawFrame)
|
||||||
|
|
||||||
val existing = RevoltAPI.channelCache[channelUpdateFrame.id]
|
val existing = StoatAPI.channelCache[channelUpdateFrame.id]
|
||||||
?: return // if we don't have the channel no point in updating it
|
?: return // if we don't have the channel no point in updating it
|
||||||
|
|
||||||
val combined = existing.mergeWithPartial(channelUpdateFrame.data)
|
val combined = existing.mergeWithPartial(channelUpdateFrame.data)
|
||||||
RevoltAPI.channelCache[channelUpdateFrame.id] = combined
|
StoatAPI.channelCache[channelUpdateFrame.id] = combined
|
||||||
|
|
||||||
database.channelQueries.upsert(
|
database.channelQueries.upsert(
|
||||||
channelUpdateFrame.id,
|
channelUpdateFrame.id,
|
||||||
|
|
@ -491,7 +491,7 @@ object RealtimeSocket {
|
||||||
combined.name,
|
combined.name,
|
||||||
combined.owner,
|
combined.owner,
|
||||||
combined.description,
|
combined.description,
|
||||||
if (combined.channelType == ChannelType.DirectMessage) combined.recipients?.firstOrNull { u -> u != RevoltAPI.selfId } else null,
|
if (combined.channelType == ChannelType.DirectMessage) combined.recipients?.firstOrNull { u -> u != StoatAPI.selfId } else null,
|
||||||
combined.icon?.id,
|
combined.icon?.id,
|
||||||
combined.lastMessageID,
|
combined.lastMessageID,
|
||||||
if (combined.active == true) 1L else 0L,
|
if (combined.active == true) 1L else 0L,
|
||||||
|
|
@ -502,14 +502,14 @@ object RealtimeSocket {
|
||||||
|
|
||||||
"ChannelCreate" -> {
|
"ChannelCreate" -> {
|
||||||
val channelCreateFrame =
|
val channelCreateFrame =
|
||||||
RevoltJson.decodeFromString(Channel.serializer(), rawFrame)
|
StoatJson.decodeFromString(Channel.serializer(), rawFrame)
|
||||||
|
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received channel create frame for ${channelCreateFrame.id}, with name ${channelCreateFrame.name}. Adding to cache."
|
"Received channel create frame for ${channelCreateFrame.id}, with name ${channelCreateFrame.name}. Adding to cache."
|
||||||
)
|
)
|
||||||
|
|
||||||
RevoltAPI.channelCache[channelCreateFrame.id!!] = channelCreateFrame
|
StoatAPI.channelCache[channelCreateFrame.id!!] = channelCreateFrame
|
||||||
database.channelQueries.upsert(
|
database.channelQueries.upsert(
|
||||||
channelCreateFrame.id,
|
channelCreateFrame.id,
|
||||||
channelCreateFrame.channelType?.value ?: ChannelType.TextChannel.value,
|
channelCreateFrame.channelType?.value ?: ChannelType.TextChannel.value,
|
||||||
|
|
@ -517,7 +517,7 @@ object RealtimeSocket {
|
||||||
channelCreateFrame.name,
|
channelCreateFrame.name,
|
||||||
channelCreateFrame.owner,
|
channelCreateFrame.owner,
|
||||||
channelCreateFrame.description,
|
channelCreateFrame.description,
|
||||||
if (channelCreateFrame.channelType == ChannelType.DirectMessage) channelCreateFrame.recipients?.firstOrNull { u -> u != RevoltAPI.selfId } else null,
|
if (channelCreateFrame.channelType == ChannelType.DirectMessage) channelCreateFrame.recipients?.firstOrNull { u -> u != StoatAPI.selfId } else null,
|
||||||
channelCreateFrame.icon?.id,
|
channelCreateFrame.icon?.id,
|
||||||
channelCreateFrame.lastMessageID,
|
channelCreateFrame.lastMessageID,
|
||||||
if (channelCreateFrame.active == true) 1L else 0L,
|
if (channelCreateFrame.active == true) 1L else 0L,
|
||||||
|
|
@ -528,13 +528,13 @@ object RealtimeSocket {
|
||||||
|
|
||||||
"ChannelDelete" -> {
|
"ChannelDelete" -> {
|
||||||
val channelDeleteFrame =
|
val channelDeleteFrame =
|
||||||
RevoltJson.decodeFromString(ChannelDeleteFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ChannelDeleteFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received channel delete frame for ${channelDeleteFrame.id}. Removing from cache."
|
"Received channel delete frame for ${channelDeleteFrame.id}. Removing from cache."
|
||||||
)
|
)
|
||||||
|
|
||||||
val currentChannel = RevoltAPI.channelCache[channelDeleteFrame.id]
|
val currentChannel = StoatAPI.channelCache[channelDeleteFrame.id]
|
||||||
if (currentChannel == null) {
|
if (currentChannel == null) {
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
|
|
@ -543,11 +543,11 @@ object RealtimeSocket {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.channelCache.remove(channelDeleteFrame.id)
|
StoatAPI.channelCache.remove(channelDeleteFrame.id)
|
||||||
database.channelQueries.delete(channelDeleteFrame.id)
|
database.channelQueries.delete(channelDeleteFrame.id)
|
||||||
|
|
||||||
if (currentChannel.server != null) {
|
if (currentChannel.server != null) {
|
||||||
val existingServer = RevoltAPI.serverCache[currentChannel.server]
|
val existingServer = StoatAPI.serverCache[currentChannel.server]
|
||||||
|
|
||||||
if (existingServer == null) {
|
if (existingServer == null) {
|
||||||
Log.d(
|
Log.d(
|
||||||
|
|
@ -557,39 +557,39 @@ object RealtimeSocket {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.serverCache[currentChannel.server] = existingServer.copy(
|
StoatAPI.serverCache[currentChannel.server] = existingServer.copy(
|
||||||
channels = existingServer.channels?.filter { it != channelDeleteFrame.id }
|
channels = existingServer.channels?.filter { it != channelDeleteFrame.id }
|
||||||
?: emptyList()
|
?: emptyList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.wsFrameChannel.send(channelDeleteFrame)
|
StoatAPI.wsFrameChannel.send(channelDeleteFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
"ChannelAck" -> {
|
"ChannelAck" -> {
|
||||||
val channelAckFrame =
|
val channelAckFrame =
|
||||||
RevoltJson.decodeFromString(ChannelAckFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ChannelAckFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received channel ack frame for ${channelAckFrame.id} with new newest ${channelAckFrame.messageId}."
|
"Received channel ack frame for ${channelAckFrame.id} with new newest ${channelAckFrame.messageId}."
|
||||||
)
|
)
|
||||||
|
|
||||||
RevoltAPI.unreads.processExternalAck(channelAckFrame.id, channelAckFrame.messageId)
|
StoatAPI.unreads.processExternalAck(channelAckFrame.id, channelAckFrame.messageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
"ServerCreate" -> {
|
"ServerCreate" -> {
|
||||||
val serverCreateFrame =
|
val serverCreateFrame =
|
||||||
RevoltJson.decodeFromString(ServerCreateFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ServerCreateFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received server create frame for ${serverCreateFrame.id}, with name ${serverCreateFrame.server.name}. Adding to cache."
|
"Received server create frame for ${serverCreateFrame.id}, with name ${serverCreateFrame.server.name}. Adding to cache."
|
||||||
)
|
)
|
||||||
|
|
||||||
RevoltAPI.serverCache[serverCreateFrame.id] = serverCreateFrame.server
|
StoatAPI.serverCache[serverCreateFrame.id] = serverCreateFrame.server
|
||||||
|
|
||||||
serverCreateFrame.channels.forEach { channel ->
|
serverCreateFrame.channels.forEach { channel ->
|
||||||
if (channel.id == null) return@forEach
|
if (channel.id == null) return@forEach
|
||||||
RevoltAPI.channelCache[channel.id] = channel
|
StoatAPI.channelCache[channel.id] = channel
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverCreateFrame.server.owner != null && serverCreateFrame.server.name != null) {
|
if (serverCreateFrame.server.owner != null && serverCreateFrame.server.name != null) {
|
||||||
|
|
@ -607,35 +607,35 @@ object RealtimeSocket {
|
||||||
|
|
||||||
"ChannelStartTyping" -> {
|
"ChannelStartTyping" -> {
|
||||||
val channelStartTypingFrame =
|
val channelStartTypingFrame =
|
||||||
RevoltJson.decodeFromString(ChannelStartTypingFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ChannelStartTypingFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received channel start typing frame for ${channelStartTypingFrame.id}."
|
"Received channel start typing frame for ${channelStartTypingFrame.id}."
|
||||||
)
|
)
|
||||||
|
|
||||||
RevoltAPI.wsFrameChannel.send(channelStartTypingFrame)
|
StoatAPI.wsFrameChannel.send(channelStartTypingFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
"ChannelStopTyping" -> {
|
"ChannelStopTyping" -> {
|
||||||
val channelStopTypingFrame =
|
val channelStopTypingFrame =
|
||||||
RevoltJson.decodeFromString(ChannelStopTypingFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ChannelStopTypingFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received channel stop typing frame for ${channelStopTypingFrame.id}."
|
"Received channel stop typing frame for ${channelStopTypingFrame.id}."
|
||||||
)
|
)
|
||||||
|
|
||||||
RevoltAPI.wsFrameChannel.send(channelStopTypingFrame)
|
StoatAPI.wsFrameChannel.send(channelStopTypingFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
"ServerUpdate" -> {
|
"ServerUpdate" -> {
|
||||||
val serverUpdateFrame =
|
val serverUpdateFrame =
|
||||||
RevoltJson.decodeFromString(ServerUpdateFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ServerUpdateFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received server update frame for ${serverUpdateFrame.id}."
|
"Received server update frame for ${serverUpdateFrame.id}."
|
||||||
)
|
)
|
||||||
|
|
||||||
val existing = RevoltAPI.serverCache[serverUpdateFrame.id]
|
val existing = StoatAPI.serverCache[serverUpdateFrame.id]
|
||||||
?: return // if we don't have the server no point in updating it
|
?: return // if we don't have the server no point in updating it
|
||||||
|
|
||||||
var updated =
|
var updated =
|
||||||
|
|
@ -650,7 +650,7 @@ object RealtimeSocket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.serverCache[serverUpdateFrame.id] = updated
|
StoatAPI.serverCache[serverUpdateFrame.id] = updated
|
||||||
|
|
||||||
if (updated.id != null && updated.owner != null && updated.name != null) {
|
if (updated.id != null && updated.owner != null && updated.name != null) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -671,25 +671,25 @@ object RealtimeSocket {
|
||||||
|
|
||||||
"ServerDelete" -> {
|
"ServerDelete" -> {
|
||||||
val serverDeleteFrame =
|
val serverDeleteFrame =
|
||||||
RevoltJson.decodeFromString(ServerDeleteFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ServerDeleteFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received server delete frame for ${serverDeleteFrame.id}."
|
"Received server delete frame for ${serverDeleteFrame.id}."
|
||||||
)
|
)
|
||||||
|
|
||||||
RevoltAPI.serverCache.remove(serverDeleteFrame.id)
|
StoatAPI.serverCache.remove(serverDeleteFrame.id)
|
||||||
database.serverQueries.delete(serverDeleteFrame.id)
|
database.serverQueries.delete(serverDeleteFrame.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
"ServerMemberUpdate" -> {
|
"ServerMemberUpdate" -> {
|
||||||
val serverMemberUpdateFrame =
|
val serverMemberUpdateFrame =
|
||||||
RevoltJson.decodeFromString(ServerMemberUpdateFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ServerMemberUpdateFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received server member update frame for ${serverMemberUpdateFrame.id.user} in ${serverMemberUpdateFrame.id.server}."
|
"Received server member update frame for ${serverMemberUpdateFrame.id.user} in ${serverMemberUpdateFrame.id.server}."
|
||||||
)
|
)
|
||||||
|
|
||||||
val existing = RevoltAPI.members.getMember(
|
val existing = StoatAPI.members.getMember(
|
||||||
serverMemberUpdateFrame.id.server,
|
serverMemberUpdateFrame.id.server,
|
||||||
serverMemberUpdateFrame.id.user
|
serverMemberUpdateFrame.id.user
|
||||||
)
|
)
|
||||||
|
|
@ -707,12 +707,12 @@ object RealtimeSocket {
|
||||||
|
|
||||||
Log.d("RealtimeSocket", "Updated member: $updated")
|
Log.d("RealtimeSocket", "Updated member: $updated")
|
||||||
|
|
||||||
RevoltAPI.members.setMember(serverMemberUpdateFrame.id.server, updated)
|
StoatAPI.members.setMember(serverMemberUpdateFrame.id.server, updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
"ServerMemberJoin" -> {
|
"ServerMemberJoin" -> {
|
||||||
val serverMemberJoinFrame =
|
val serverMemberJoinFrame =
|
||||||
RevoltJson.decodeFromString(ServerMemberJoinFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ServerMemberJoinFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received server member join frame for ${serverMemberJoinFrame.user} in ${serverMemberJoinFrame.id}."
|
"Received server member join frame for ${serverMemberJoinFrame.user} in ${serverMemberJoinFrame.id}."
|
||||||
|
|
@ -720,18 +720,18 @@ object RealtimeSocket {
|
||||||
|
|
||||||
val member = fetchMember(serverMemberJoinFrame.id, serverMemberJoinFrame.user)
|
val member = fetchMember(serverMemberJoinFrame.id, serverMemberJoinFrame.user)
|
||||||
|
|
||||||
RevoltAPI.members.setMember(serverMemberJoinFrame.id, member)
|
StoatAPI.members.setMember(serverMemberJoinFrame.id, member)
|
||||||
}
|
}
|
||||||
|
|
||||||
"ServerMemberLeave" -> {
|
"ServerMemberLeave" -> {
|
||||||
val serverMemberLeaveFrame =
|
val serverMemberLeaveFrame =
|
||||||
RevoltJson.decodeFromString(ServerMemberLeaveFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ServerMemberLeaveFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received server member leave frame for ${serverMemberLeaveFrame.user} in ${serverMemberLeaveFrame.id}."
|
"Received server member leave frame for ${serverMemberLeaveFrame.user} in ${serverMemberLeaveFrame.id}."
|
||||||
)
|
)
|
||||||
|
|
||||||
RevoltAPI.members.removeMember(
|
StoatAPI.members.removeMember(
|
||||||
serverMemberLeaveFrame.id,
|
serverMemberLeaveFrame.id,
|
||||||
serverMemberLeaveFrame.user
|
serverMemberLeaveFrame.user
|
||||||
)
|
)
|
||||||
|
|
@ -739,13 +739,13 @@ object RealtimeSocket {
|
||||||
|
|
||||||
"ServerRoleUpdate" -> {
|
"ServerRoleUpdate" -> {
|
||||||
val serverRoleUpdateFrame =
|
val serverRoleUpdateFrame =
|
||||||
RevoltJson.decodeFromString(ServerRoleUpdateFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ServerRoleUpdateFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received server role update frame for ${serverRoleUpdateFrame.id}."
|
"Received server role update frame for ${serverRoleUpdateFrame.id}."
|
||||||
)
|
)
|
||||||
|
|
||||||
val server = RevoltAPI.serverCache[serverRoleUpdateFrame.id]
|
val server = StoatAPI.serverCache[serverRoleUpdateFrame.id]
|
||||||
if (server == null) {
|
if (server == null) {
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
|
|
@ -767,7 +767,7 @@ object RealtimeSocket {
|
||||||
Pair(serverRoleUpdateFrame.roleId, newRole)
|
Pair(serverRoleUpdateFrame.roleId, newRole)
|
||||||
) ?: mapOf(serverRoleUpdateFrame.roleId to newRole)
|
) ?: mapOf(serverRoleUpdateFrame.roleId to newRole)
|
||||||
)
|
)
|
||||||
RevoltAPI.serverCache[serverRoleUpdateFrame.id] = newServer
|
StoatAPI.serverCache[serverRoleUpdateFrame.id] = newServer
|
||||||
} else {
|
} else {
|
||||||
// True role update.
|
// True role update.
|
||||||
Log.d(
|
Log.d(
|
||||||
|
|
@ -780,19 +780,19 @@ object RealtimeSocket {
|
||||||
Pair(serverRoleUpdateFrame.roleId, updatedRole)
|
Pair(serverRoleUpdateFrame.roleId, updatedRole)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
RevoltAPI.serverCache[serverRoleUpdateFrame.id] = newServer
|
StoatAPI.serverCache[serverRoleUpdateFrame.id] = newServer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"ServerRoleDelete" -> {
|
"ServerRoleDelete" -> {
|
||||||
val serverRoleDeleteFrame =
|
val serverRoleDeleteFrame =
|
||||||
RevoltJson.decodeFromString(ServerRoleDeleteFrame.serializer(), rawFrame)
|
StoatJson.decodeFromString(ServerRoleDeleteFrame.serializer(), rawFrame)
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
"Received server role delete frame for ${serverRoleDeleteFrame.id} and role ${serverRoleDeleteFrame.roleId}."
|
"Received server role delete frame for ${serverRoleDeleteFrame.id} and role ${serverRoleDeleteFrame.roleId}."
|
||||||
)
|
)
|
||||||
|
|
||||||
val server = RevoltAPI.serverCache[serverRoleDeleteFrame.id]
|
val server = StoatAPI.serverCache[serverRoleDeleteFrame.id]
|
||||||
if (server == null) {
|
if (server == null) {
|
||||||
Log.d(
|
Log.d(
|
||||||
"RealtimeSocket",
|
"RealtimeSocket",
|
||||||
|
|
@ -804,7 +804,7 @@ object RealtimeSocket {
|
||||||
val newRoles = server.roles?.toMutableMap() ?: mutableMapOf()
|
val newRoles = server.roles?.toMutableMap() ?: mutableMapOf()
|
||||||
newRoles.remove(serverRoleDeleteFrame.roleId)
|
newRoles.remove(serverRoleDeleteFrame.roleId)
|
||||||
|
|
||||||
RevoltAPI.serverCache[serverRoleDeleteFrame.id] =
|
StoatAPI.serverCache[serverRoleDeleteFrame.id] =
|
||||||
server.copy(roles = newRoles)
|
server.copy(roles = newRoles)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -820,7 +820,7 @@ object RealtimeSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun pushReconnectEvent() {
|
private suspend fun pushReconnectEvent() {
|
||||||
RevoltAPI.wsFrameChannel.send(RealtimeSocketFrames.Reconnected)
|
StoatAPI.wsFrameChannel.send(RealtimeSocketFrames.Reconnected)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun beginTyping(channelId: String) {
|
suspend fun beginTyping(channelId: String) {
|
||||||
|
|
@ -828,7 +828,7 @@ object RealtimeSocket {
|
||||||
|
|
||||||
val beginTypingFrame = BeginTypingFrame("BeginTyping", channelId)
|
val beginTypingFrame = BeginTypingFrame("BeginTyping", channelId)
|
||||||
socket?.send(
|
socket?.send(
|
||||||
RevoltJson.encodeToString(
|
StoatJson.encodeToString(
|
||||||
BeginTypingFrame.serializer(),
|
BeginTypingFrame.serializer(),
|
||||||
beginTypingFrame
|
beginTypingFrame
|
||||||
)
|
)
|
||||||
|
|
@ -840,7 +840,7 @@ object RealtimeSocket {
|
||||||
|
|
||||||
val endTypingFrame = EndTypingFrame("EndTyping", channelId)
|
val endTypingFrame = EndTypingFrame("EndTyping", channelId)
|
||||||
socket?.send(
|
socket?.send(
|
||||||
RevoltJson.encodeToString(
|
StoatJson.encodeToString(
|
||||||
EndTypingFrame.serializer(),
|
EndTypingFrame.serializer(),
|
||||||
endTypingFrame
|
endTypingFrame
|
||||||
)
|
)
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
package chat.revolt.api.realtime.frames.receivable
|
package chat.stoat.api.realtime.frames.receivable
|
||||||
|
|
||||||
import chat.revolt.api.schemas.Channel
|
import chat.stoat.api.schemas.Channel
|
||||||
import chat.revolt.api.schemas.ChannelVoiceState
|
import chat.stoat.api.schemas.ChannelVoiceState
|
||||||
import chat.revolt.api.schemas.Embed
|
import chat.stoat.api.schemas.Embed
|
||||||
import chat.revolt.api.schemas.Emoji
|
import chat.stoat.api.schemas.Emoji
|
||||||
import chat.revolt.api.schemas.Member
|
import chat.stoat.api.schemas.Member
|
||||||
import chat.revolt.api.schemas.Message
|
import chat.stoat.api.schemas.Message
|
||||||
import chat.revolt.api.schemas.Role
|
import chat.stoat.api.schemas.Role
|
||||||
import chat.revolt.api.schemas.Server
|
import chat.stoat.api.schemas.Server
|
||||||
import chat.revolt.api.schemas.ServerUserChoice
|
import chat.stoat.api.schemas.ServerUserChoice
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.realtime.frames.sendable
|
package chat.stoat.api.realtime.frames.sendable
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package chat.revolt.api.routes.account
|
package chat.stoat.api.routes.account
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import io.ktor.client.request.setBody
|
import io.ktor.client.request.setBody
|
||||||
import io.ktor.client.statement.HttpResponse
|
import io.ktor.client.statement.HttpResponse
|
||||||
|
|
@ -104,22 +104,22 @@ data class EmailPasswordAssessment(
|
||||||
val proceedMfa: Boolean = false,
|
val proceedMfa: Boolean = false,
|
||||||
val mfaSpec: MfaLoginSpec? = null,
|
val mfaSpec: MfaLoginSpec? = null,
|
||||||
val firstUserHints: UserHints? = null,
|
val firstUserHints: UserHints? = null,
|
||||||
val error: RevoltError? = null
|
val error: StoatAPIError? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun negotiateAuthentication(email: String, password: String): EmailPasswordAssessment {
|
suspend fun negotiateAuthentication(email: String, password: String): EmailPasswordAssessment {
|
||||||
val sessionName = friendlySessionName()
|
val sessionName = friendlySessionName()
|
||||||
|
|
||||||
val response: HttpResponse = RevoltHttp.post("/auth/session/login".api()) {
|
val response: HttpResponse = StoatHttp.post("/auth/session/login".api()) {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(LoginNegotiation(email, password, sessionName, null))
|
setBody(LoginNegotiation(email, password, sessionName, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseContent = response.bodyAsText()
|
val responseContent = response.bodyAsText()
|
||||||
Log.d("Revolt", "negotiateAuthentication: $responseContent")
|
Log.d("Stoat", "negotiateAuthentication: $responseContent")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), responseContent)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), responseContent)
|
||||||
return EmailPasswordAssessment(error = error)
|
return EmailPasswordAssessment(error = error)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -127,22 +127,22 @@ suspend fun negotiateAuthentication(email: String, password: String): EmailPassw
|
||||||
|
|
||||||
if (response.status == HttpStatusCode.InternalServerError) {
|
if (response.status == HttpStatusCode.InternalServerError) {
|
||||||
return EmailPasswordAssessment(
|
return EmailPasswordAssessment(
|
||||||
error = RevoltError(
|
error = StoatAPIError(
|
||||||
"InternalServerError"
|
"InternalServerError"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseJson = RevoltJson.decodeFromString(MfaCheck.serializer(), responseContent)
|
val responseJson = StoatJson.decodeFromString(MfaCheck.serializer(), responseContent)
|
||||||
|
|
||||||
return when (responseJson.result) {
|
return when (responseJson.result) {
|
||||||
"Success" -> EmailPasswordAssessment(
|
"Success" -> EmailPasswordAssessment(
|
||||||
firstUserHints = RevoltJson.decodeFromString(UserHints.serializer(), responseContent)
|
firstUserHints = StoatJson.decodeFromString(UserHints.serializer(), responseContent)
|
||||||
)
|
)
|
||||||
|
|
||||||
"MFA" -> EmailPasswordAssessment(
|
"MFA" -> EmailPasswordAssessment(
|
||||||
proceedMfa = true,
|
proceedMfa = true,
|
||||||
mfaSpec = RevoltJson.decodeFromString(MfaLoginSpec.serializer(), responseContent)
|
mfaSpec = StoatJson.decodeFromString(MfaLoginSpec.serializer(), responseContent)
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> throw Exception("Unknown result: ${responseJson.result}")
|
else -> throw Exception("Unknown result: ${responseJson.result}")
|
||||||
|
|
@ -153,23 +153,23 @@ suspend fun authenticateWithMfaTotpCode(
|
||||||
mfaTicket: String,
|
mfaTicket: String,
|
||||||
mfaResponse: MfaResponseTotpCode
|
mfaResponse: MfaResponseTotpCode
|
||||||
): EmailPasswordAssessment {
|
): EmailPasswordAssessment {
|
||||||
val response: HttpResponse = RevoltHttp.post("/auth/session/login".api()) {
|
val response: HttpResponse = StoatHttp.post("/auth/session/login".api()) {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(LoginMfaAmendmentTotpCode(mfaTicket, mfaResponse, friendlySessionName()))
|
setBody(LoginMfaAmendmentTotpCode(mfaTicket, mfaResponse, friendlySessionName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response.bodyAsText())
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response.bodyAsText())
|
||||||
return EmailPasswordAssessment(error = error)
|
return EmailPasswordAssessment(error = error)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseContent = response.bodyAsText()
|
val responseContent = response.bodyAsText()
|
||||||
Log.d("Revolt", "authenticateWithMfaTotpCode: $responseContent")
|
Log.d("Stoat", "authenticateWithMfaTotpCode: $responseContent")
|
||||||
|
|
||||||
return EmailPasswordAssessment(
|
return EmailPasswordAssessment(
|
||||||
firstUserHints = RevoltJson.decodeFromString(UserHints.serializer(), responseContent)
|
firstUserHints = StoatJson.decodeFromString(UserHints.serializer(), responseContent)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,26 +177,26 @@ suspend fun authenticateWithMfaRecoveryCode(
|
||||||
mfaTicket: String,
|
mfaTicket: String,
|
||||||
mfaResponse: MfaResponseRecoveryCode
|
mfaResponse: MfaResponseRecoveryCode
|
||||||
): EmailPasswordAssessment {
|
): EmailPasswordAssessment {
|
||||||
val response: HttpResponse = RevoltHttp.post("/auth/session/login".api()) {
|
val response: HttpResponse = StoatHttp.post("/auth/session/login".api()) {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(LoginMfaAmendmentRecoveryCode(mfaTicket, mfaResponse, friendlySessionName()))
|
setBody(LoginMfaAmendmentRecoveryCode(mfaTicket, mfaResponse, friendlySessionName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response.bodyAsText())
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response.bodyAsText())
|
||||||
return EmailPasswordAssessment(error = error)
|
return EmailPasswordAssessment(error = error)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseContent = response.bodyAsText()
|
val responseContent = response.bodyAsText()
|
||||||
Log.d("Revolt", "authenticateWithMfaRecoveryCode: $responseContent")
|
Log.d("Stoat", "authenticateWithMfaRecoveryCode: $responseContent")
|
||||||
|
|
||||||
return EmailPasswordAssessment(
|
return EmailPasswordAssessment(
|
||||||
firstUserHints = RevoltJson.decodeFromString(UserHints.serializer(), responseContent)
|
firstUserHints = StoatJson.decodeFromString(UserHints.serializer(), responseContent)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun friendlySessionName(): String {
|
fun friendlySessionName(): String {
|
||||||
return "Revolt Android on ${Build.MANUFACTURER} ${Build.MODEL}"
|
return "Stoat for Android on ${Build.MANUFACTURER} ${Build.MODEL}"
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package chat.revolt.api.routes.account
|
package chat.stoat.api.routes.account
|
||||||
|
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.schemas.RsResult
|
import chat.stoat.api.schemas.RsResult
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import io.ktor.client.request.setBody
|
import io.ktor.client.request.setBody
|
||||||
import io.ktor.client.statement.bodyAsText
|
import io.ktor.client.statement.bodyAsText
|
||||||
|
|
@ -21,8 +21,8 @@ data class RegistrationBody(
|
||||||
val captcha: String
|
val captcha: String
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun register(body: RegistrationBody): RsResult<Unit, RevoltError> {
|
suspend fun register(body: RegistrationBody): RsResult<Unit, StoatAPIError> {
|
||||||
val response = RevoltHttp.post("/auth/account/create".api()) {
|
val response = StoatHttp.post("/auth/account/create".api()) {
|
||||||
setBody(body)
|
setBody(body)
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
}
|
}
|
||||||
|
|
@ -30,7 +30,7 @@ suspend fun register(body: RegistrationBody): RsResult<Unit, RevoltError> {
|
||||||
val responseContent = response.bodyAsText()
|
val responseContent = response.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), responseContent)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), responseContent)
|
||||||
return RsResult.err(error)
|
return RsResult.err(error)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package chat.revolt.api.routes.auth
|
package chat.stoat.api.routes.auth
|
||||||
|
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import chat.revolt.api.schemas.Session
|
import chat.stoat.api.schemas.Session
|
||||||
import io.ktor.client.request.delete
|
import io.ktor.client.request.delete
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.parameter
|
import io.ktor.client.request.parameter
|
||||||
|
|
@ -11,21 +11,21 @@ import io.ktor.client.statement.bodyAsText
|
||||||
import kotlinx.serialization.builtins.ListSerializer
|
import kotlinx.serialization.builtins.ListSerializer
|
||||||
|
|
||||||
suspend fun fetchAllSessions(): List<Session> {
|
suspend fun fetchAllSessions(): List<Session> {
|
||||||
val response = RevoltHttp.get("/auth/session/all".api())
|
val response = StoatHttp.get("/auth/session/all".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(
|
return StoatJson.decodeFromString(
|
||||||
ListSerializer(Session.serializer()),
|
ListSerializer(Session.serializer()),
|
||||||
response
|
response
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun logoutSessionById(id: String) {
|
suspend fun logoutSessionById(id: String) {
|
||||||
RevoltHttp.delete("/auth/session/$id".api())
|
StoatHttp.delete("/auth/session/$id".api())
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun logoutAllSessions(includingSelf: Boolean = false) {
|
suspend fun logoutAllSessions(includingSelf: Boolean = false) {
|
||||||
RevoltHttp.delete("/auth/session/all".api()) {
|
StoatHttp.delete("/auth/session/all".api()) {
|
||||||
parameter("revoke_self", includingSelf)
|
parameter("revoke_self", includingSelf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
package chat.revolt.api.routes.channel
|
package chat.stoat.api.routes.channel
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import chat.revolt.api.internals.ULID
|
import chat.stoat.api.internals.ULID
|
||||||
import chat.revolt.api.schemas.Channel
|
import chat.stoat.api.schemas.Channel
|
||||||
import chat.revolt.api.schemas.Message
|
import chat.stoat.api.schemas.Message
|
||||||
import chat.revolt.api.schemas.MessagesInChannel
|
import chat.stoat.api.schemas.MessagesInChannel
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
import io.ktor.client.request.delete
|
import io.ktor.client.request.delete
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.header
|
import io.ktor.client.request.header
|
||||||
|
|
@ -37,7 +37,7 @@ suspend fun fetchMessagesFromChannel(
|
||||||
nearby: String? = null,
|
nearby: String? = null,
|
||||||
sort: String? = null
|
sort: String? = null
|
||||||
): MessagesInChannel {
|
): MessagesInChannel {
|
||||||
val response = RevoltHttp.get("/channels/$channelId/messages".api()) {
|
val response = StoatHttp.get("/channels/$channelId/messages".api()) {
|
||||||
parameter("limit", limit)
|
parameter("limit", limit)
|
||||||
parameter("include_users", includeUsers)
|
parameter("include_users", includeUsers)
|
||||||
|
|
||||||
|
|
@ -49,12 +49,12 @@ suspend fun fetchMessagesFromChannel(
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
if (includeUsers) {
|
if (includeUsers) {
|
||||||
return RevoltJson.decodeFromString(
|
return StoatJson.decodeFromString(
|
||||||
MessagesInChannel.serializer(),
|
MessagesInChannel.serializer(),
|
||||||
response
|
response
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val messages = RevoltJson.decodeFromString(
|
val messages = StoatJson.decodeFromString(
|
||||||
ListSerializer(Message.serializer()),
|
ListSerializer(Message.serializer()),
|
||||||
response
|
response
|
||||||
)
|
)
|
||||||
|
|
@ -104,7 +104,7 @@ suspend fun sendMessage(
|
||||||
attachments: List<String>? = null,
|
attachments: List<String>? = null,
|
||||||
idempotencyKey: String = ULID.makeNext()
|
idempotencyKey: String = ULID.makeNext()
|
||||||
): String {
|
): String {
|
||||||
val response = RevoltHttp.post("/channels/$channelId/messages".api()) {
|
val response = StoatHttp.post("/channels/$channelId/messages".api()) {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(
|
setBody(
|
||||||
SendMessageBody(
|
SendMessageBody(
|
||||||
|
|
@ -122,7 +122,7 @@ suspend fun sendMessage(
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun editMessage(channelId: String, messageId: String, newContent: String? = null) {
|
suspend fun editMessage(channelId: String, messageId: String, newContent: String? = null) {
|
||||||
val response = RevoltHttp.patch("/channels/$channelId/messages/$messageId".api()) {
|
val response = StoatHttp.patch("/channels/$channelId/messages/$messageId".api()) {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(
|
setBody(
|
||||||
EditMessageBody(
|
EditMessageBody(
|
||||||
|
|
@ -133,7 +133,7 @@ suspend fun editMessage(channelId: String, messageId: String, newContent: String
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Error(error.type)
|
throw Error(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -141,55 +141,55 @@ suspend fun editMessage(channelId: String, messageId: String, newContent: String
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteMessage(channelId: String, messageId: String) {
|
suspend fun deleteMessage(channelId: String, messageId: String) {
|
||||||
RevoltHttp.delete("/channels/$channelId/messages/$messageId".api())
|
StoatHttp.delete("/channels/$channelId/messages/$messageId".api())
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun ackChannel(channelId: String, messageId: String = ULID.makeNext()) {
|
suspend fun ackChannel(channelId: String, messageId: String = ULID.makeNext()) {
|
||||||
RevoltHttp.put("/channels/$channelId/ack/$messageId".api())
|
StoatHttp.put("/channels/$channelId/ack/$messageId".api())
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchSingleChannel(channelId: String): Channel {
|
suspend fun fetchSingleChannel(channelId: String): Channel {
|
||||||
val response = RevoltHttp.get("/channels/$channelId".api())
|
val response = StoatHttp.get("/channels/$channelId".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(
|
return StoatJson.decodeFromString(
|
||||||
Channel.serializer(),
|
Channel.serializer(),
|
||||||
response
|
response
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchGroupParticipants(channelId: String): List<User> {
|
suspend fun fetchGroupParticipants(channelId: String): List<User> {
|
||||||
val response = RevoltHttp.get("/channels/$channelId/members".api())
|
val response = StoatHttp.get("/channels/$channelId/members".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(
|
return StoatJson.decodeFromString(
|
||||||
ListSerializer(User.serializer()),
|
ListSerializer(User.serializer()),
|
||||||
response
|
response
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun createInvite(channelId: String): CreateInviteResponse {
|
suspend fun createInvite(channelId: String): CreateInviteResponse {
|
||||||
val response = RevoltHttp.post("/channels/$channelId/invites".api())
|
val response = StoatHttp.post("/channels/$channelId/invites".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
if (error.type != "Server") throw Error(error.type)
|
if (error.type != "Server") throw Error(error.type)
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(CreateInviteResponse.serializer(), response)
|
return StoatJson.decodeFromString(CreateInviteResponse.serializer(), response)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchSingleMessage(channelId: String, messageId: String): Message {
|
suspend fun fetchSingleMessage(channelId: String, messageId: String): Message {
|
||||||
val response = RevoltHttp.get("/channels/$channelId/messages/$messageId".api())
|
val response = StoatHttp.get("/channels/$channelId/messages/$messageId".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(
|
return StoatJson.decodeFromString(
|
||||||
Message.serializer(),
|
Message.serializer(),
|
||||||
response
|
response
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun leaveDeleteOrCloseChannel(channelId: String, leaveSilently: Boolean = false) {
|
suspend fun leaveDeleteOrCloseChannel(channelId: String, leaveSilently: Boolean = false) {
|
||||||
RevoltHttp.delete("/channels/$channelId".api()) {
|
StoatHttp.delete("/channels/$channelId".api()) {
|
||||||
parameter("leave_silently", leaveSilently)
|
parameter("leave_silently", leaveSilently)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -207,33 +207,33 @@ suspend fun patchChannel(
|
||||||
val body = mutableMapOf<String, JsonElement>()
|
val body = mutableMapOf<String, JsonElement>()
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
body["name"] = RevoltJson.encodeToJsonElement(String.serializer(), name)
|
body["name"] = StoatJson.encodeToJsonElement(String.serializer(), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (description != null) {
|
if (description != null) {
|
||||||
body["description"] = RevoltJson.encodeToJsonElement(String.serializer(), description)
|
body["description"] = StoatJson.encodeToJsonElement(String.serializer(), description)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
body["icon"] = RevoltJson.encodeToJsonElement(String.serializer(), icon)
|
body["icon"] = StoatJson.encodeToJsonElement(String.serializer(), icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (banner != null) {
|
if (banner != null) {
|
||||||
body["banner"] = RevoltJson.encodeToJsonElement(String.serializer(), banner)
|
body["banner"] = StoatJson.encodeToJsonElement(String.serializer(), banner)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remove != null) {
|
if (remove != null) {
|
||||||
body["remove"] = RevoltJson.encodeToJsonElement(ListSerializer(String.serializer()), remove)
|
body["remove"] = StoatJson.encodeToJsonElement(ListSerializer(String.serializer()), remove)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsfw != null) {
|
if (nsfw != null) {
|
||||||
body["nsfw"] = RevoltJson.encodeToJsonElement(Boolean.serializer(), nsfw)
|
body["nsfw"] = StoatJson.encodeToJsonElement(Boolean.serializer(), nsfw)
|
||||||
}
|
}
|
||||||
|
|
||||||
val response = RevoltHttp.patch("/channels/$channelId".api()) {
|
val response = StoatHttp.patch("/channels/$channelId".api()) {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(
|
setBody(
|
||||||
RevoltJson.encodeToString(
|
StoatJson.encodeToString(
|
||||||
MapSerializer(
|
MapSerializer(
|
||||||
String.serializer(),
|
String.serializer(),
|
||||||
JsonElement.serializer()
|
JsonElement.serializer()
|
||||||
|
|
@ -245,14 +245,14 @@ suspend fun patchChannel(
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pure) {
|
if (!pure) {
|
||||||
val channel = RevoltJson.decodeFromString(Channel.serializer(), response)
|
val channel = StoatJson.decodeFromString(Channel.serializer(), response)
|
||||||
RevoltAPI.channelCache[channelId] = channel
|
StoatAPI.channelCache[channelId] = channel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package chat.revolt.api.routes.channel
|
package chat.stoat.api.routes.channel
|
||||||
|
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import chat.revolt.api.schemas.Channel
|
import chat.stoat.api.schemas.Channel
|
||||||
import chat.revolt.screens.create.MAX_ADDABLE_PEOPLE_IN_GROUP
|
import chat.stoat.screens.create.MAX_ADDABLE_PEOPLE_IN_GROUP
|
||||||
import io.ktor.client.request.delete
|
import io.ktor.client.request.delete
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import io.ktor.client.request.put
|
import io.ktor.client.request.put
|
||||||
|
|
@ -28,23 +28,23 @@ suspend fun createGroupDM(name: String, members: List<String>): Channel {
|
||||||
throw Exception("Too many members, maximum is $MAX_ADDABLE_PEOPLE_IN_GROUP")
|
throw Exception("Too many members, maximum is $MAX_ADDABLE_PEOPLE_IN_GROUP")
|
||||||
}
|
}
|
||||||
|
|
||||||
val response = RevoltHttp.post("/channels/create".api()) {
|
val response = StoatHttp.post("/channels/create".api()) {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(CreateGroupDMBody(name, members))
|
setBody(CreateGroupDMBody(name, members))
|
||||||
}.bodyAsText()
|
}.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Error(error.type)
|
throw Error(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(Channel.serializer(), response)
|
return StoatJson.decodeFromString(Channel.serializer(), response)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun removeMember(channelId: String, userId: String) {
|
suspend fun removeMember(channelId: String, userId: String) {
|
||||||
val response = RevoltHttp.delete("/channels/$channelId/recipients/$userId".api())
|
val response = StoatHttp.delete("/channels/$channelId/recipients/$userId".api())
|
||||||
|
|
||||||
if (!response.status.isSuccess()) {
|
if (!response.status.isSuccess()) {
|
||||||
throw Error(response.status.toString())
|
throw Error(response.status.toString())
|
||||||
|
|
@ -52,7 +52,7 @@ suspend fun removeMember(channelId: String, userId: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun addMember(channelId: String, userId: String) {
|
suspend fun addMember(channelId: String, userId: String) {
|
||||||
val response = RevoltHttp.put("/channels/$channelId/recipients/$userId".api())
|
val response = StoatHttp.put("/channels/$channelId/recipients/$userId".api())
|
||||||
|
|
||||||
if (!response.status.isSuccess()) {
|
if (!response.status.isSuccess()) {
|
||||||
throw Error(response.status.toString())
|
throw Error(response.status.toString())
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package chat.stoat.api.routes.channel
|
||||||
|
|
||||||
|
import chat.stoat.api.StoatHttp
|
||||||
|
import chat.stoat.api.api
|
||||||
|
import io.ktor.client.request.delete
|
||||||
|
import io.ktor.client.request.put
|
||||||
|
|
||||||
|
suspend fun react(channelId: String, messageId: String, emoji: String) {
|
||||||
|
StoatHttp.put("/channels/$channelId/messages/$messageId/reactions/$emoji".api())
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun unreact(channelId: String, messageId: String, emoji: String) {
|
||||||
|
StoatHttp.delete("/channels/$channelId/messages/$messageId/reactions/$emoji".api())
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package chat.stoat.api.routes.custom
|
||||||
|
|
||||||
|
import chat.stoat.api.StoatHttp
|
||||||
|
import chat.stoat.api.StoatJson
|
||||||
|
import chat.stoat.api.api
|
||||||
|
import chat.stoat.api.schemas.Emoji
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import io.ktor.client.statement.bodyAsText
|
||||||
|
|
||||||
|
suspend fun fetchEmoji(id: String): Emoji {
|
||||||
|
val response = StoatHttp.get("/custom/emoji/$id".api()).bodyAsText()
|
||||||
|
return StoatJson.decodeFromString(
|
||||||
|
Emoji.serializer(),
|
||||||
|
response
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package chat.stoat.api.routes.invites
|
||||||
|
|
||||||
|
import chat.stoat.api.StoatAPIError
|
||||||
|
import chat.stoat.api.StoatHttp
|
||||||
|
import chat.stoat.api.StoatJson
|
||||||
|
import chat.stoat.api.api
|
||||||
|
import chat.stoat.api.schemas.Invite
|
||||||
|
import chat.stoat.api.schemas.InviteJoined
|
||||||
|
import chat.stoat.api.schemas.RsResult
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import io.ktor.client.request.post
|
||||||
|
import io.ktor.client.statement.bodyAsText
|
||||||
|
import kotlinx.serialization.SerializationException
|
||||||
|
|
||||||
|
suspend fun fetchInviteByCode(code: String): RsResult<Invite, StoatAPIError> {
|
||||||
|
val response = StoatHttp.get("/invites/$code".api())
|
||||||
|
.bodyAsText()
|
||||||
|
|
||||||
|
try {
|
||||||
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
|
if (error.type != "Server") return RsResult.err(error)
|
||||||
|
} catch (e: SerializationException) {
|
||||||
|
// Not an error
|
||||||
|
}
|
||||||
|
|
||||||
|
val invite = StoatJson.decodeFromString(Invite.serializer(), response)
|
||||||
|
return RsResult.ok(invite)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun joinInviteByCode(code: String): RsResult<InviteJoined, StoatAPIError> {
|
||||||
|
val response = StoatHttp.post("/invites/$code".api())
|
||||||
|
.bodyAsText()
|
||||||
|
|
||||||
|
try {
|
||||||
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
|
if (error.type != "Server") return RsResult.err(error)
|
||||||
|
} catch (e: SerializationException) {
|
||||||
|
// Not an error
|
||||||
|
}
|
||||||
|
|
||||||
|
val invite = StoatJson.decodeFromString(InviteJoined.serializer(), response)
|
||||||
|
return RsResult.ok(invite)
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package chat.revolt.api.routes.microservices.autumn
|
package chat.stoat.api.routes.microservices.autumn
|
||||||
|
|
||||||
import chat.revolt.api.HitRateLimitException
|
import chat.stoat.api.HitRateLimitException
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.stoat.api.STOAT_FILES
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.schemas.AutumnError
|
import chat.stoat.api.schemas.AutumnError
|
||||||
import chat.revolt.api.schemas.AutumnId
|
import chat.stoat.api.schemas.AutumnId
|
||||||
import io.ktor.client.plugins.onUpload
|
import io.ktor.client.plugins.onUpload
|
||||||
import io.ktor.client.request.forms.MultiPartFormDataContent
|
import io.ktor.client.request.forms.MultiPartFormDataContent
|
||||||
import io.ktor.client.request.forms.formData
|
import io.ktor.client.request.forms.formData
|
||||||
|
|
@ -37,9 +37,9 @@ suspend fun uploadToAutumn(
|
||||||
contentType: ContentType,
|
contentType: ContentType,
|
||||||
onProgress: (Long, Long) -> Unit = { _, _ -> }
|
onProgress: (Long, Long) -> Unit = { _, _ -> }
|
||||||
): String {
|
): String {
|
||||||
val uploadUrl = "$REVOLT_FILES/$tag"
|
val uploadUrl = "$STOAT_FILES/$tag"
|
||||||
|
|
||||||
val response = RevoltHttp.post(uploadUrl) {
|
val response = StoatHttp.post(uploadUrl) {
|
||||||
setBody(
|
setBody(
|
||||||
MultiPartFormDataContent(
|
MultiPartFormDataContent(
|
||||||
formData {
|
formData {
|
||||||
|
|
@ -54,18 +54,18 @@ suspend fun uploadToAutumn(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
header(RevoltAPI.TOKEN_HEADER_NAME, RevoltAPI.sessionToken)
|
header(StoatAPI.TOKEN_HEADER_NAME, StoatAPI.sessionToken)
|
||||||
onUpload { bytesSentTotal, contentLength ->
|
onUpload { bytesSentTotal, contentLength ->
|
||||||
contentLength?.let { onProgress(bytesSentTotal, it) }
|
contentLength?.let { onProgress(bytesSentTotal, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val autumnId = RevoltJson.decodeFromString(AutumnId.serializer(), response.bodyAsText())
|
val autumnId = StoatJson.decodeFromString(AutumnId.serializer(), response.bodyAsText())
|
||||||
return autumnId.id
|
return autumnId.id
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(AutumnError.serializer(), response.bodyAsText())
|
val error = StoatJson.decodeFromString(AutumnError.serializer(), response.bodyAsText())
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
if (response.status == HttpStatusCode.TooManyRequests) {
|
if (response.status == HttpStatusCode.TooManyRequests) {
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package chat.revolt.api.routes.microservices.geo
|
package chat.stoat.api.routes.microservices.geo
|
||||||
|
|
||||||
import chat.revolt.api.HitRateLimitException
|
import chat.stoat.api.HitRateLimitException
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.buildUserAgent
|
import chat.stoat.api.buildUserAgent
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.header
|
import io.ktor.client.request.header
|
||||||
import io.ktor.client.statement.bodyAsText
|
import io.ktor.client.statement.bodyAsText
|
||||||
|
|
@ -18,12 +18,12 @@ data class GeoResponse(
|
||||||
|
|
||||||
suspend fun queryGeo(): GeoResponse {
|
suspend fun queryGeo(): GeoResponse {
|
||||||
try {
|
try {
|
||||||
val response = RevoltHttp.get("https://geo.revolt.chat/?client=android") {
|
val response = StoatHttp.get("https://geo.revolt.chat/?client=android") {
|
||||||
header("User-Agent", buildUserAgent("Ktor queryGeo"))
|
header("User-Agent", buildUserAgent("Ktor queryGeo"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.status == HttpStatusCode.OK) {
|
if (response.status == HttpStatusCode.OK) {
|
||||||
return RevoltJson.decodeFromString(response.bodyAsText())
|
return StoatJson.decodeFromString(response.bodyAsText())
|
||||||
} else throw Exception("Failed to query geo: ${response.status.value} ${response.status.description}")
|
} else throw Exception("Failed to query geo: ${response.status.value} ${response.status.description}")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw Exception("Failed to query geo: ${e.message}", e).also {
|
throw Exception("Failed to query geo: ${e.message}", e).also {
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package chat.stoat.api.routes.microservices.health
|
||||||
|
|
||||||
|
import chat.stoat.api.StoatHttp
|
||||||
|
import chat.stoat.api.StoatJson
|
||||||
|
import chat.stoat.api.schemas.HealthNotice
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import io.ktor.client.statement.bodyAsText
|
||||||
|
|
||||||
|
suspend fun healthCheck(): HealthNotice {
|
||||||
|
val response = StoatHttp.get("https://health.revolt.chat/api/health").bodyAsText()
|
||||||
|
return StoatJson.decodeFromString(HealthNotice.serializer(), response)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package chat.stoat.api.routes.microservices.january
|
||||||
|
|
||||||
|
import chat.stoat.api.STOAT_PROXY
|
||||||
|
import java.net.URLEncoder
|
||||||
|
|
||||||
|
fun asJanuaryProxyUrl(url: String): String {
|
||||||
|
return "$STOAT_PROXY/proxy?url=${URLEncoder.encode(url, "utf-8")}"
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package chat.revolt.api.routes.misc
|
package chat.stoat.api.routes.misc
|
||||||
|
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import io.ktor.client.call.body
|
import io.ktor.client.call.body
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
|
|
@ -61,5 +61,5 @@ data class LiveKitNode(
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun getRootRoute(): Root {
|
suspend fun getRootRoute(): Root {
|
||||||
return RevoltHttp.get("/".api()).body()
|
return StoatHttp.get("/".api()).body()
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package chat.revolt.api.routes.onboard
|
package chat.stoat.api.routes.onboard
|
||||||
|
|
||||||
import chat.revolt.api.RateLimitResponse
|
import chat.stoat.api.RateLimitResponse
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import chat.revolt.api.schemas.RsResult
|
import chat.stoat.api.schemas.RsResult
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.header
|
import io.ktor.client.request.header
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
|
|
@ -23,22 +23,22 @@ data class OnboardingResponse(
|
||||||
val onboarding: Boolean
|
val onboarding: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun needsOnboarding(sessionToken: String = RevoltAPI.sessionToken): Boolean {
|
suspend fun needsOnboarding(sessionToken: String = StoatAPI.sessionToken): Boolean {
|
||||||
val response = RevoltHttp.get("/onboard/hello".api()) {
|
val response = StoatHttp.get("/onboard/hello".api()) {
|
||||||
header(RevoltAPI.TOKEN_HEADER_NAME, sessionToken)
|
header(StoatAPI.TOKEN_HEADER_NAME, sessionToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseContent = response.bodyAsText()
|
val responseContent = response.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val rateLimitResponse =
|
val rateLimitResponse =
|
||||||
RevoltJson.decodeFromString(RateLimitResponse.serializer(), responseContent)
|
StoatJson.decodeFromString(RateLimitResponse.serializer(), responseContent)
|
||||||
throw rateLimitResponse.toException()
|
throw rateLimitResponse.toException()
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// good path
|
// good path
|
||||||
}
|
}
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(OnboardingResponse.serializer(), responseContent).onboarding
|
return StoatJson.decodeFromString(OnboardingResponse.serializer(), responseContent).onboarding
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|
@ -48,26 +48,26 @@ data class OnboardingCompletionBody(
|
||||||
|
|
||||||
suspend fun completeOnboarding(
|
suspend fun completeOnboarding(
|
||||||
body: OnboardingCompletionBody,
|
body: OnboardingCompletionBody,
|
||||||
sessionToken: String = RevoltAPI.sessionToken
|
sessionToken: String = StoatAPI.sessionToken
|
||||||
): RsResult<Unit, RevoltError> {
|
): RsResult<Unit, StoatAPIError> {
|
||||||
val response = RevoltHttp.post("/onboard/complete".api()) {
|
val response = StoatHttp.post("/onboard/complete".api()) {
|
||||||
setBody(body)
|
setBody(body)
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
header(RevoltAPI.TOKEN_HEADER_NAME, sessionToken)
|
header(StoatAPI.TOKEN_HEADER_NAME, sessionToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.status == HttpStatusCode.Conflict) {
|
if (response.status == HttpStatusCode.Conflict) {
|
||||||
return RsResult.err(RevoltError("UsernameTaken"))
|
return RsResult.err(StoatAPIError("UsernameTaken"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.status == HttpStatusCode.BadRequest) {
|
if (response.status == HttpStatusCode.BadRequest) {
|
||||||
return RsResult.err(RevoltError("InvalidUsername"))
|
return RsResult.err(StoatAPIError("InvalidUsername"))
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseContent = response.bodyAsText()
|
val responseContent = response.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), responseContent)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), responseContent)
|
||||||
return RsResult.err(error)
|
return RsResult.err(error)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package chat.revolt.api.routes.push
|
package chat.stoat.api.routes.push
|
||||||
|
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.routes.account.WebPushData
|
import chat.stoat.api.routes.account.WebPushData
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import io.ktor.client.request.setBody
|
import io.ktor.client.request.setBody
|
||||||
import io.ktor.http.ContentType
|
import io.ktor.http.ContentType
|
||||||
|
|
@ -19,7 +19,7 @@ suspend fun subscribePush(
|
||||||
auth = auth
|
auth = auth
|
||||||
)
|
)
|
||||||
|
|
||||||
RevoltHttp.post("/push/subscribe".api()) {
|
StoatHttp.post("/push/subscribe".api()) {
|
||||||
setBody(data)
|
setBody(data)
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
package chat.revolt.api.routes.safety
|
package chat.stoat.api.routes.safety
|
||||||
|
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.schemas.ContentReportReason
|
import chat.stoat.api.schemas.ContentReportReason
|
||||||
import chat.revolt.api.schemas.FullMessageReport
|
import chat.stoat.api.schemas.FullMessageReport
|
||||||
import chat.revolt.api.schemas.FullServerReport
|
import chat.stoat.api.schemas.FullServerReport
|
||||||
import chat.revolt.api.schemas.FullUserReport
|
import chat.stoat.api.schemas.FullUserReport
|
||||||
import chat.revolt.api.schemas.MessageReport
|
import chat.stoat.api.schemas.MessageReport
|
||||||
import chat.revolt.api.schemas.ServerReport
|
import chat.stoat.api.schemas.ServerReport
|
||||||
import chat.revolt.api.schemas.UserReport
|
import chat.stoat.api.schemas.UserReport
|
||||||
import chat.revolt.api.schemas.UserReportReason
|
import chat.stoat.api.schemas.UserReportReason
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import io.ktor.client.request.setBody
|
import io.ktor.client.request.setBody
|
||||||
import io.ktor.client.statement.bodyAsText
|
import io.ktor.client.statement.bodyAsText
|
||||||
|
|
@ -31,9 +31,9 @@ suspend fun putMessageReport(
|
||||||
additional_context = additionalContext
|
additional_context = additionalContext
|
||||||
)
|
)
|
||||||
|
|
||||||
val response = RevoltHttp.post("/safety/report".api()) {
|
val response = StoatHttp.post("/safety/report".api()) {
|
||||||
setBody(
|
setBody(
|
||||||
RevoltJson.encodeToString(
|
StoatJson.encodeToString(
|
||||||
FullMessageReport.serializer(),
|
FullMessageReport.serializer(),
|
||||||
fullMessageReport
|
fullMessageReport
|
||||||
)
|
)
|
||||||
|
|
@ -42,7 +42,7 @@ suspend fun putMessageReport(
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Error(error.type)
|
throw Error(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -63,9 +63,9 @@ suspend fun putServerReport(
|
||||||
additional_context = additionalContext
|
additional_context = additionalContext
|
||||||
)
|
)
|
||||||
|
|
||||||
val response = RevoltHttp.post("/safety/report".api()) {
|
val response = StoatHttp.post("/safety/report".api()) {
|
||||||
setBody(
|
setBody(
|
||||||
RevoltJson.encodeToString(
|
StoatJson.encodeToString(
|
||||||
FullServerReport.serializer(),
|
FullServerReport.serializer(),
|
||||||
fullServerReport
|
fullServerReport
|
||||||
)
|
)
|
||||||
|
|
@ -74,7 +74,7 @@ suspend fun putServerReport(
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Error(error.type)
|
throw Error(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -95,9 +95,9 @@ suspend fun putUserReport(
|
||||||
additional_context = additionalContext
|
additional_context = additionalContext
|
||||||
)
|
)
|
||||||
|
|
||||||
val response = RevoltHttp.post("/safety/report".api()) {
|
val response = StoatHttp.post("/safety/report".api()) {
|
||||||
setBody(
|
setBody(
|
||||||
RevoltJson.encodeToString(
|
StoatJson.encodeToString(
|
||||||
FullUserReport.serializer(),
|
FullUserReport.serializer(),
|
||||||
fullUserReport
|
fullUserReport
|
||||||
)
|
)
|
||||||
|
|
@ -106,7 +106,7 @@ suspend fun putUserReport(
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Error(error.type)
|
throw Error(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
package chat.revolt.api.routes.server
|
package chat.stoat.api.routes.server
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import chat.revolt.api.schemas.Member
|
import chat.stoat.api.schemas.Member
|
||||||
import chat.revolt.api.schemas.ServerWithChannelObjects
|
import chat.stoat.api.schemas.ServerWithChannelObjects
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
import io.ktor.client.request.delete
|
import io.ktor.client.request.delete
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.parameter
|
import io.ktor.client.request.parameter
|
||||||
|
|
@ -25,7 +25,7 @@ data class FetchMembersResponse(
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun ackServer(serverId: String) {
|
suspend fun ackServer(serverId: String) {
|
||||||
RevoltHttp.put("/servers/$serverId/ack".api())
|
StoatHttp.put("/servers/$serverId/ack".api())
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchMembers(
|
suspend fun fetchMembers(
|
||||||
|
|
@ -33,55 +33,55 @@ suspend fun fetchMembers(
|
||||||
includeOffline: Boolean = false,
|
includeOffline: Boolean = false,
|
||||||
pure: Boolean = false
|
pure: Boolean = false
|
||||||
): FetchMembersResponse {
|
): FetchMembersResponse {
|
||||||
val response = RevoltHttp.get("/servers/$serverId/members".api()) {
|
val response = StoatHttp.get("/servers/$serverId/members".api()) {
|
||||||
parameter("exclude_offline", !includeOffline)
|
parameter("exclude_offline", !includeOffline)
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseContent = response.bodyAsText()
|
val responseContent = response.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), responseContent)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), responseContent)
|
||||||
throw Error(error.type)
|
throw Error(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
val membersResponse =
|
val membersResponse =
|
||||||
RevoltJson.decodeFromString(FetchMembersResponse.serializer(), responseContent)
|
StoatJson.decodeFromString(FetchMembersResponse.serializer(), responseContent)
|
||||||
|
|
||||||
if (pure) {
|
if (pure) {
|
||||||
return membersResponse
|
return membersResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
membersResponse.members.forEach { member ->
|
membersResponse.members.forEach { member ->
|
||||||
if (!RevoltAPI.members.hasMember(serverId, member.id!!.user)) {
|
if (!StoatAPI.members.hasMember(serverId, member.id!!.user)) {
|
||||||
RevoltAPI.members.setMember(serverId, member)
|
StoatAPI.members.setMember(serverId, member)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
membersResponse.users.forEach { user ->
|
membersResponse.users.forEach { user ->
|
||||||
user.id?.let { RevoltAPI.userCache.putIfAbsent(it, user) }
|
user.id?.let { StoatAPI.userCache.putIfAbsent(it, user) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return membersResponse
|
return membersResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchMember(serverId: String, userId: String, pure: Boolean = false): Member {
|
suspend fun fetchMember(serverId: String, userId: String, pure: Boolean = false): Member {
|
||||||
val response = RevoltHttp.get("/servers/$serverId/members/$userId".api())
|
val response = StoatHttp.get("/servers/$serverId/members/$userId".api())
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response.bodyAsText())
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response.bodyAsText())
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
val member = RevoltJson.decodeFromString(Member.serializer(), response.bodyAsText())
|
val member = StoatJson.decodeFromString(Member.serializer(), response.bodyAsText())
|
||||||
|
|
||||||
if (!pure) {
|
if (!pure) {
|
||||||
member.id?.let {
|
member.id?.let {
|
||||||
if (!RevoltAPI.members.hasMember(serverId, it.user)) {
|
if (!StoatAPI.members.hasMember(serverId, it.user)) {
|
||||||
RevoltAPI.members.setMember(serverId, member)
|
StoatAPI.members.setMember(serverId, member)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +90,7 @@ suspend fun fetchMember(serverId: String, userId: String, pure: Boolean = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun leaveOrDeleteServer(serverId: String, leaveSilently: Boolean = false) {
|
suspend fun leaveOrDeleteServer(serverId: String, leaveSilently: Boolean = false) {
|
||||||
RevoltHttp.delete("/servers/$serverId".api()) {
|
StoatHttp.delete("/servers/$serverId".api()) {
|
||||||
parameter("leave_silently", leaveSilently)
|
parameter("leave_silently", leaveSilently)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,16 +109,16 @@ suspend fun createServer(
|
||||||
): ServerWithChannelObjects {
|
): ServerWithChannelObjects {
|
||||||
val body = ServerCreationBody(name, description, nsfw)
|
val body = ServerCreationBody(name, description, nsfw)
|
||||||
|
|
||||||
val response = RevoltHttp.post("/servers/create".api()) {
|
val response = StoatHttp.post("/servers/create".api()) {
|
||||||
setBody(RevoltJson.encodeToString(ServerCreationBody.serializer(), body))
|
setBody(StoatJson.encodeToString(ServerCreationBody.serializer(), body))
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response.bodyAsText())
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response.bodyAsText())
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(ServerWithChannelObjects.serializer(), response.bodyAsText())
|
return StoatJson.decodeFromString(ServerWithChannelObjects.serializer(), response.bodyAsText())
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package chat.revolt.api.routes.sync
|
package chat.stoat.api.routes.sync
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import io.ktor.client.request.parameter
|
import io.ktor.client.request.parameter
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import io.ktor.client.request.setBody
|
import io.ktor.client.request.setBody
|
||||||
|
|
@ -17,13 +17,13 @@ import kotlinx.serialization.json.JsonArray
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SyncedSetting(val timestamp: Long, val value: String)
|
data class SyncedSetting(val timestamp: Long, val value: String)
|
||||||
|
|
||||||
suspend fun getKeys(vararg keys: String, revoltToken: String): Map<String, SyncedSetting> {
|
suspend fun getKeys(vararg keys: String, token: String): Map<String, SyncedSetting> {
|
||||||
val response = RevoltHttp.post("/sync/settings/fetch".api()) {
|
val response = StoatHttp.post("/sync/settings/fetch".api()) {
|
||||||
headers.append(RevoltAPI.TOKEN_HEADER_NAME, revoltToken)
|
headers.append(StoatAPI.TOKEN_HEADER_NAME, token)
|
||||||
|
|
||||||
// format: {"keys": ["key1", "key2"]}
|
// format: {"keys": ["key1", "key2"]}
|
||||||
setBody(
|
setBody(
|
||||||
RevoltJson.encodeToString(
|
StoatJson.encodeToString(
|
||||||
MapSerializer(
|
MapSerializer(
|
||||||
String.serializer(),
|
String.serializer(),
|
||||||
ListSerializer(String.serializer())
|
ListSerializer(String.serializer())
|
||||||
|
|
@ -33,7 +33,7 @@ suspend fun getKeys(vararg keys: String, revoltToken: String): Map<String, Synce
|
||||||
)
|
)
|
||||||
}.bodyAsText()
|
}.bodyAsText()
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(
|
return StoatJson.decodeFromString(
|
||||||
MapSerializer(
|
MapSerializer(
|
||||||
String.serializer(),
|
String.serializer(),
|
||||||
JsonArray.serializer()
|
JsonArray.serializer()
|
||||||
|
|
@ -52,16 +52,16 @@ suspend fun getKeys(vararg keys: String, revoltToken: String): Map<String, Synce
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getKeys(vararg keys: String): Map<String, SyncedSetting> {
|
suspend fun getKeys(vararg keys: String): Map<String, SyncedSetting> {
|
||||||
return getKeys(*keys, revoltToken = RevoltAPI.sessionToken)
|
return getKeys(*keys, token = StoatAPI.sessionToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun setKey(key: String, value: String) {
|
suspend fun setKey(key: String, value: String) {
|
||||||
RevoltHttp.post("/sync/settings/set".api()) {
|
StoatHttp.post("/sync/settings/set".api()) {
|
||||||
parameter("timestamp", System.currentTimeMillis())
|
parameter("timestamp", System.currentTimeMillis())
|
||||||
|
|
||||||
// format: {"key": "value"}
|
// format: {"key": "value"}
|
||||||
setBody(
|
setBody(
|
||||||
RevoltJson.encodeToString(
|
StoatJson.encodeToString(
|
||||||
MapSerializer(
|
MapSerializer(
|
||||||
String.serializer(),
|
String.serializer(),
|
||||||
String.serializer()
|
String.serializer()
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
package chat.revolt.api.routes.sync
|
package chat.stoat.api.routes.sync
|
||||||
|
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import chat.revolt.api.schemas.ChannelUnreadResponse
|
import chat.stoat.api.schemas.ChannelUnreadResponse
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.statement.bodyAsText
|
import io.ktor.client.statement.bodyAsText
|
||||||
import kotlinx.serialization.builtins.ListSerializer
|
import kotlinx.serialization.builtins.ListSerializer
|
||||||
|
|
||||||
suspend fun syncUnreads(): List<ChannelUnreadResponse> {
|
suspend fun syncUnreads(): List<ChannelUnreadResponse> {
|
||||||
val response = RevoltHttp.get("/sync/unreads".api())
|
val response = StoatHttp.get("/sync/unreads".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(
|
return StoatJson.decodeFromString(
|
||||||
ListSerializer(ChannelUnreadResponse.serializer()),
|
ListSerializer(ChannelUnreadResponse.serializer()),
|
||||||
response
|
response
|
||||||
)
|
)
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package chat.stoat.api.routes.user
|
||||||
|
|
||||||
|
import chat.stoat.api.StoatAPIError
|
||||||
|
import chat.stoat.api.StoatHttp
|
||||||
|
import chat.stoat.api.StoatJson
|
||||||
|
import chat.stoat.api.api
|
||||||
|
import chat.stoat.api.schemas.Channel
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import io.ktor.client.statement.bodyAsText
|
||||||
|
import kotlinx.serialization.SerializationException
|
||||||
|
|
||||||
|
suspend fun openDM(userId: String): Channel {
|
||||||
|
val response = StoatHttp.get("/users/$userId/dm".api())
|
||||||
|
.bodyAsText()
|
||||||
|
|
||||||
|
try {
|
||||||
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
|
throw Error(error.type)
|
||||||
|
} catch (e: SerializationException) {
|
||||||
|
// Not an error
|
||||||
|
}
|
||||||
|
|
||||||
|
return StoatJson.decodeFromString(Channel.serializer(), response)
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package chat.revolt.api.routes.user
|
package chat.stoat.api.routes.user
|
||||||
|
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import io.ktor.client.request.delete
|
import io.ktor.client.request.delete
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import io.ktor.client.request.put
|
import io.ktor.client.request.put
|
||||||
|
|
@ -14,11 +14,11 @@ import io.ktor.http.contentType
|
||||||
import kotlinx.serialization.SerializationException
|
import kotlinx.serialization.SerializationException
|
||||||
|
|
||||||
suspend fun blockUser(userId: String) {
|
suspend fun blockUser(userId: String) {
|
||||||
val response = RevoltHttp.put("/users/$userId/block".api())
|
val response = StoatHttp.put("/users/$userId/block".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -26,11 +26,11 @@ suspend fun blockUser(userId: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun unblockUser(userId: String) {
|
suspend fun unblockUser(userId: String) {
|
||||||
val response = RevoltHttp.delete("/users/$userId/block".api())
|
val response = StoatHttp.delete("/users/$userId/block".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -38,14 +38,14 @@ suspend fun unblockUser(userId: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun friendUser(username: String) {
|
suspend fun friendUser(username: String) {
|
||||||
val response = RevoltHttp.post("/users/friend".api()) {
|
val response = StoatHttp.post("/users/friend".api()) {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(mapOf("username" to username))
|
setBody(mapOf("username" to username))
|
||||||
}
|
}
|
||||||
val body = response.bodyAsText()
|
val body = response.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), body)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), body)
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -53,11 +53,11 @@ suspend fun friendUser(username: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun acceptFriendRequest(userId: String) {
|
suspend fun acceptFriendRequest(userId: String) {
|
||||||
val response = RevoltHttp.put("/users/$userId/friend".api())
|
val response = StoatHttp.put("/users/$userId/friend".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -65,11 +65,11 @@ suspend fun acceptFriendRequest(userId: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun unfriendUser(userId: String) {
|
suspend fun unfriendUser(userId: String) {
|
||||||
val response = RevoltHttp.delete("/users/$userId/friend".api())
|
val response = StoatHttp.delete("/users/$userId/friend".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
package chat.revolt.api.routes.user
|
package chat.stoat.api.routes.user
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import chat.revolt.api.schemas.Profile
|
import chat.stoat.api.schemas.Profile
|
||||||
import chat.revolt.api.schemas.Status
|
import chat.stoat.api.schemas.Status
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.patch
|
import io.ktor.client.request.patch
|
||||||
import io.ktor.client.request.setBody
|
import io.ktor.client.request.setBody
|
||||||
|
|
@ -21,24 +21,24 @@ import kotlinx.serialization.builtins.serializer
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
|
||||||
suspend fun fetchSelf(): User {
|
suspend fun fetchSelf(): User {
|
||||||
val response = RevoltHttp.get("/users/@me".api())
|
val response = StoatHttp.get("/users/@me".api())
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
val user = RevoltJson.decodeFromString(User.serializer(), response)
|
val user = StoatJson.decodeFromString(User.serializer(), response)
|
||||||
|
|
||||||
if (user.id == null) {
|
if (user.id == null) {
|
||||||
throw Exception("Self user ID is null")
|
throw Exception("Self user ID is null")
|
||||||
}
|
}
|
||||||
|
|
||||||
RevoltAPI.userCache[user.id] = user
|
StoatAPI.userCache[user.id] = user
|
||||||
RevoltAPI.selfId = user.id
|
StoatAPI.selfId = user.id
|
||||||
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
@ -54,11 +54,11 @@ suspend fun patchSelf(
|
||||||
val body = mutableMapOf<String, JsonElement>()
|
val body = mutableMapOf<String, JsonElement>()
|
||||||
|
|
||||||
if (status != null) {
|
if (status != null) {
|
||||||
body["status"] = RevoltJson.encodeToJsonElement(Status.serializer(), status)
|
body["status"] = StoatJson.encodeToJsonElement(Status.serializer(), status)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avatar != null) {
|
if (avatar != null) {
|
||||||
body["avatar"] = RevoltJson.encodeToJsonElement(String.serializer(), avatar)
|
body["avatar"] = StoatJson.encodeToJsonElement(String.serializer(), avatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (background != null || bio != null) {
|
if (background != null || bio != null) {
|
||||||
|
|
@ -71,7 +71,7 @@ suspend fun patchSelf(
|
||||||
profileMap["content"] = bio
|
profileMap["content"] = bio
|
||||||
}
|
}
|
||||||
|
|
||||||
body["profile"] = RevoltJson.encodeToJsonElement(
|
body["profile"] = StoatJson.encodeToJsonElement(
|
||||||
MapSerializer(
|
MapSerializer(
|
||||||
String.serializer(),
|
String.serializer(),
|
||||||
String.serializer()
|
String.serializer()
|
||||||
|
|
@ -81,13 +81,13 @@ suspend fun patchSelf(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remove != null) {
|
if (remove != null) {
|
||||||
body["remove"] = RevoltJson.encodeToJsonElement(ListSerializer(String.serializer()), remove)
|
body["remove"] = StoatJson.encodeToJsonElement(ListSerializer(String.serializer()), remove)
|
||||||
}
|
}
|
||||||
|
|
||||||
val response = RevoltHttp.patch("/users/@me".api()) {
|
val response = StoatHttp.patch("/users/@me".api()) {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(
|
setBody(
|
||||||
RevoltJson.encodeToString(
|
StoatJson.encodeToString(
|
||||||
MapSerializer(
|
MapSerializer(
|
||||||
String.serializer(),
|
String.serializer(),
|
||||||
JsonElement.serializer()
|
JsonElement.serializer()
|
||||||
|
|
@ -98,21 +98,21 @@ suspend fun patchSelf(
|
||||||
}
|
}
|
||||||
.bodyAsText()
|
.bodyAsText()
|
||||||
|
|
||||||
if (RevoltAPI.selfId == null) {
|
if (StoatAPI.selfId == null) {
|
||||||
throw Error("Self ID is null")
|
throw Error("Self ID is null")
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentUser = RevoltAPI.userCache[RevoltAPI.selfId] ?: fetchSelf()
|
val currentUser = StoatAPI.userCache[StoatAPI.selfId] ?: fetchSelf()
|
||||||
val newUserKeys = RevoltJson.decodeFromString(User.serializer(), response)
|
val newUserKeys = StoatJson.decodeFromString(User.serializer(), response)
|
||||||
val mergedUser = currentUser.mergeWithPartial(newUserKeys)
|
val mergedUser = currentUser.mergeWithPartial(newUserKeys)
|
||||||
|
|
||||||
if (!pure) {
|
if (!pure) {
|
||||||
RevoltAPI.userCache[RevoltAPI.selfId!!] = mergedUser
|
StoatAPI.userCache[StoatAPI.selfId!!] = mergedUser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchUser(id: String): User {
|
suspend fun fetchUser(id: String): User {
|
||||||
val res = RevoltHttp.get("/users/$id".api())
|
val res = StoatHttp.get("/users/$id".api())
|
||||||
|
|
||||||
if (res.status.value == 404) {
|
if (res.status.value == 404) {
|
||||||
return User.getPlaceholder(id)
|
return User.getPlaceholder(id)
|
||||||
|
|
@ -121,42 +121,42 @@ suspend fun fetchUser(id: String): User {
|
||||||
val response = res.bodyAsText()
|
val response = res.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
val user = RevoltJson.decodeFromString(User.serializer(), response)
|
val user = StoatJson.decodeFromString(User.serializer(), response)
|
||||||
|
|
||||||
user.id?.let {
|
user.id?.let {
|
||||||
RevoltAPI.userCache[it] = user
|
StoatAPI.userCache[it] = user
|
||||||
}
|
}
|
||||||
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getOrFetchUser(id: String): User {
|
suspend fun getOrFetchUser(id: String): User {
|
||||||
return RevoltAPI.userCache[id] ?: fetchUser(id)
|
return StoatAPI.userCache[id] ?: fetchUser(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun addUserIfUnknown(id: String) {
|
suspend fun addUserIfUnknown(id: String) {
|
||||||
if (RevoltAPI.userCache[id] == null) {
|
if (StoatAPI.userCache[id] == null) {
|
||||||
RevoltAPI.userCache[id] = fetchUser(id)
|
StoatAPI.userCache[id] = fetchUser(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchUserProfile(id: String): Profile {
|
suspend fun fetchUserProfile(id: String): Profile {
|
||||||
val res = RevoltHttp.get("/users/$id/profile".api())
|
val res = StoatHttp.get("/users/$id/profile".api())
|
||||||
|
|
||||||
val response = res.bodyAsText()
|
val response = res.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(Profile.serializer(), response)
|
return StoatJson.decodeFromString(Profile.serializer(), response)
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package chat.revolt.api.routes.voice
|
package chat.stoat.api.routes.voice
|
||||||
|
|
||||||
import chat.revolt.api.RevoltError
|
import chat.stoat.api.StoatAPIError
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.stoat.api.StoatHttp
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.api
|
import chat.stoat.api.api
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import io.ktor.client.request.setBody
|
import io.ktor.client.request.setBody
|
||||||
import io.ktor.client.statement.bodyAsText
|
import io.ktor.client.statement.bodyAsText
|
||||||
|
|
@ -19,17 +19,17 @@ data class JoinCallResponse(
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun joinCall(channelId: String, nodeName: String): JoinCallResponse {
|
suspend fun joinCall(channelId: String, nodeName: String): JoinCallResponse {
|
||||||
val response = RevoltHttp.post("/channels/$channelId/join_call".api()) {
|
val response = StoatHttp.post("/channels/$channelId/join_call".api()) {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(mapOf("node" to nodeName))
|
setBody(mapOf("node" to nodeName))
|
||||||
}.bodyAsText()
|
}.bodyAsText()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
val error = StoatJson.decodeFromString(StoatAPIError.serializer(), response)
|
||||||
throw Exception(error.type)
|
throw Exception(error.type)
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
// Not an error
|
// Not an error
|
||||||
}
|
}
|
||||||
|
|
||||||
return RevoltJson.decodeFromString(JoinCallResponse.serializer(), response)
|
return StoatJson.decodeFromString(JoinCallResponse.serializer(), response)
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
@ -10,6 +10,6 @@ data class Session(
|
||||||
val name: String
|
val name: String
|
||||||
) {
|
) {
|
||||||
fun isCurrent(): Boolean {
|
fun isCurrent(): Boolean {
|
||||||
return id == RevoltAPI.sessionId
|
return id == StoatAPI.sessionId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
|
|
@ -111,7 +111,7 @@ enum class ChannelType(val value: String) {
|
||||||
override val descriptor: SerialDescriptor
|
override val descriptor: SerialDescriptor
|
||||||
get() {
|
get() {
|
||||||
return PrimitiveSerialDescriptor(
|
return PrimitiveSerialDescriptor(
|
||||||
"chat.revolt.api.schemas.ChannelType",
|
"chat.stoat.api.schemas.ChannelType",
|
||||||
PrimitiveKind.STRING
|
PrimitiveKind.STRING
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import chat.revolt.api.REVOLT_APP
|
import chat.stoat.api.STOAT_WEB_APP
|
||||||
import chat.revolt.api.REVOLT_INVITES
|
import chat.stoat.api.STOAT_INVITES
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
@ -52,10 +52,10 @@ data class InviteJoined(
|
||||||
|
|
||||||
fun Uri.isInviteUri(): Boolean {
|
fun Uri.isInviteUri(): Boolean {
|
||||||
val firstPathSegmentIsInvite = this.pathSegments.firstOrNull() == "invite"
|
val firstPathSegmentIsInvite = this.pathSegments.firstOrNull() == "invite"
|
||||||
val isAppRevoltChat = this.host == REVOLT_APP.toUri().host
|
val isStoatChat = this.host == STOAT_WEB_APP.toUri().host
|
||||||
val matchRvltGG = this.host == REVOLT_INVITES.toUri().host
|
val matchRvltGG = this.host == STOAT_INVITES.toUri().host
|
||||||
|
|
||||||
val matchApp = isAppRevoltChat && firstPathSegmentIsInvite
|
val matchApp = isStoatChat && firstPathSegmentIsInvite
|
||||||
|
|
||||||
val hasEnoughSegments =
|
val hasEnoughSegments =
|
||||||
if (matchApp) this.pathSegments.size == 2 else this.pathSegments.size == 1
|
if (matchApp) this.pathSegments.size == 2 else this.pathSegments.size == 1
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
@ -24,14 +24,14 @@ data class Message(
|
||||||
val interactions: InteractionsDescription? = null,
|
val interactions: InteractionsDescription? = null,
|
||||||
val pinned: Boolean? = null,
|
val pinned: Boolean? = null,
|
||||||
/**
|
/**
|
||||||
* See [chat.revolt.api.internals.MessageFlag]
|
* See [chat.stoat.api.internals.MessageFlag]
|
||||||
*/
|
*/
|
||||||
val flags: Int? = null,
|
val flags: Int? = null,
|
||||||
val type: String? = null, // this is _only_ used for websocket events!
|
val type: String? = null, // this is _only_ used for websocket events!
|
||||||
val tail: Boolean? = null // this is used to determine if the message is the last in a message group
|
val tail: Boolean? = null // this is used to determine if the message is the last in a message group
|
||||||
) {
|
) {
|
||||||
fun getAuthor(): User? {
|
fun getAuthor(): User? {
|
||||||
return author?.let { RevoltAPI.userCache[it] }
|
return author?.let { StoatAPI.userCache[it] }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mergeWithPartial(partial: Message): Message {
|
fun mergeWithPartial(partial: Message): Message {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -29,7 +29,7 @@ enum class ContentReportReason(val value: String) {
|
||||||
override val descriptor: SerialDescriptor
|
override val descriptor: SerialDescriptor
|
||||||
get() {
|
get() {
|
||||||
return PrimitiveSerialDescriptor(
|
return PrimitiveSerialDescriptor(
|
||||||
"chat.revolt.api.schemas.ContentReportReason",
|
"chat.stoat.api.schemas.ContentReportReason",
|
||||||
PrimitiveKind.STRING
|
PrimitiveKind.STRING
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +73,7 @@ enum class UserReportReason(val value: String) {
|
||||||
override val descriptor: SerialDescriptor
|
override val descriptor: SerialDescriptor
|
||||||
get() {
|
get() {
|
||||||
return PrimitiveSerialDescriptor(
|
return PrimitiveSerialDescriptor(
|
||||||
"chat.revolt.api.schemas.UserReportReason",
|
"chat.stoat.api.schemas.UserReportReason",
|
||||||
PrimitiveKind.STRING
|
PrimitiveKind.STRING
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import chat.revolt.ui.theme.OverridableColourScheme
|
import chat.stoat.ui.theme.OverridableColourScheme
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ data class AndroidSpecificSettingsSpecialEmbedSettings(
|
||||||
data class AndroidSpecificSettings(
|
data class AndroidSpecificSettings(
|
||||||
/**
|
/**
|
||||||
* The theme to use for the app.
|
* The theme to use for the app.
|
||||||
* Can be one of `{ None, Revolt, Light, M3Dynamic, Amoled }`
|
* Can be one of `{ None, Default, Light, M3Dynamic, Amoled }`
|
||||||
*/
|
*/
|
||||||
var theme: String? = null,
|
var theme: String? = null,
|
||||||
/**
|
/**
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
// Result class similar to Rust std::result::Result
|
// Result class similar to Rust std::result::Result
|
||||||
data class RsResult<V, E>(val value: V?, val error: E?) {
|
data class RsResult<V, E>(val value: V?, val error: E?) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.schemas
|
package chat.stoat.api.schemas
|
||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package chat.revolt.api.settings
|
package chat.stoat.api.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import chat.revolt.BuildConfig
|
import chat.stoat.BuildConfig
|
||||||
import chat.revolt.RevoltApplication
|
import chat.stoat.StoatApplication
|
||||||
import chat.revolt.persistence.KVStorage
|
import chat.stoat.persistence.KVStorage
|
||||||
|
|
||||||
class ExperimentInstance(default: Boolean) {
|
class ExperimentInstance(default: Boolean) {
|
||||||
private var _isEnabled by mutableStateOf(default)
|
private var _isEnabled by mutableStateOf(default)
|
||||||
|
|
@ -32,7 +32,7 @@ object Experiments {
|
||||||
val useFinalMarkdownRenderer = ExperimentInstance(false)
|
val useFinalMarkdownRenderer = ExperimentInstance(false)
|
||||||
|
|
||||||
suspend fun hydrateWithKv() {
|
suspend fun hydrateWithKv() {
|
||||||
val kvStorage = KVStorage(RevoltApplication.instance)
|
val kvStorage = KVStorage(StoatApplication.instance)
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
LoadedSettings.experimentsEnabled = true
|
LoadedSettings.experimentsEnabled = true
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package chat.revolt.api.settings
|
package chat.stoat.api.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.internals.SpecialUsers
|
import chat.stoat.api.internals.SpecialUsers
|
||||||
|
|
||||||
annotation class FeatureFlag(val name: String)
|
annotation class FeatureFlag(val name: String)
|
||||||
annotation class Treatment(val description: String)
|
annotation class Treatment(val description: String)
|
||||||
|
|
@ -73,7 +73,7 @@ object FeatureFlags {
|
||||||
@FeatureFlag("LabsAccessControl")
|
@FeatureFlag("LabsAccessControl")
|
||||||
var labsAccessControl by mutableStateOf<LabsAccessControlVariates>(
|
var labsAccessControl by mutableStateOf<LabsAccessControlVariates>(
|
||||||
LabsAccessControlVariates.Restricted {
|
LabsAccessControlVariates.Restricted {
|
||||||
RevoltAPI.selfId == SpecialUsers.JENNIFER
|
StoatAPI.selfId == SpecialUsers.JENNIFER
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ object FeatureFlags {
|
||||||
@FeatureFlag("UserCards")
|
@FeatureFlag("UserCards")
|
||||||
var userCards by mutableStateOf<UserCardsVariates>(
|
var userCards by mutableStateOf<UserCardsVariates>(
|
||||||
UserCardsVariates.Restricted {
|
UserCardsVariates.Restricted {
|
||||||
RevoltAPI.selfId?.endsWith("Z") == true
|
StoatAPI.selfId?.endsWith("Z") == true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package chat.revolt.api.settings
|
package chat.stoat.api.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import chat.revolt.api.routes.microservices.geo.GeoResponse
|
import chat.stoat.api.routes.microservices.geo.GeoResponse
|
||||||
|
|
||||||
object GeoStateProvider {
|
object GeoStateProvider {
|
||||||
var geoState by mutableStateOf<GeoResponse?>(null)
|
var geoState by mutableStateOf<GeoResponse?>(null)
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package chat.revolt.api.settings
|
package chat.stoat.api.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import chat.revolt.api.schemas.AndroidSpecificSettingsSpecialEmbedSettings
|
import chat.stoat.api.schemas.AndroidSpecificSettingsSpecialEmbedSettings
|
||||||
import chat.revolt.ui.theme.Theme
|
import chat.stoat.ui.theme.Theme
|
||||||
import chat.revolt.ui.theme.getDefaultTheme
|
import chat.stoat.ui.theme.getDefaultTheme
|
||||||
|
|
||||||
enum class MessageReplyStyle {
|
enum class MessageReplyStyle {
|
||||||
None,
|
None,
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.api.settings
|
package chat.stoat.api.settings
|
||||||
|
|
||||||
object NotificationSettingsProvider {
|
object NotificationSettingsProvider {
|
||||||
fun isChannelMuted(channelId: String, serverId: String?): Boolean {
|
fun isChannelMuted(channelId: String, serverId: String?): Boolean {
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
package chat.revolt.api.settings
|
package chat.stoat.api.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.routes.sync.getKeys
|
import chat.stoat.api.routes.sync.getKeys
|
||||||
import chat.revolt.api.routes.sync.setKey
|
import chat.stoat.api.routes.sync.setKey
|
||||||
import chat.revolt.api.schemas.AndroidSpecificSettings
|
import chat.stoat.api.schemas.AndroidSpecificSettings
|
||||||
import chat.revolt.api.schemas.NotificationSettings
|
import chat.stoat.api.schemas.NotificationSettings
|
||||||
import chat.revolt.api.schemas.OrderingSettings
|
import chat.stoat.api.schemas.OrderingSettings
|
||||||
import chat.revolt.api.schemas._NotificationSettingsToParse
|
import chat.stoat.api.schemas._NotificationSettingsToParse
|
||||||
import kotlinx.serialization.json.JsonPrimitive
|
import kotlinx.serialization.json.JsonPrimitive
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
|
|
@ -40,14 +40,14 @@ object SyncedSettings {
|
||||||
val notifications: NotificationSettings
|
val notifications: NotificationSettings
|
||||||
get() = _notifications.value
|
get() = _notifications.value
|
||||||
|
|
||||||
suspend fun fetch(revoltToken: String = RevoltAPI.sessionToken) {
|
suspend fun fetch(apiToken: String = StoatAPI.sessionToken) {
|
||||||
try {
|
try {
|
||||||
val settings =
|
val settings =
|
||||||
getKeys("ordering", "android", "notifications", revoltToken = revoltToken)
|
getKeys("ordering", "android", "notifications", token = apiToken)
|
||||||
|
|
||||||
settings["ordering"]?.let {
|
settings["ordering"]?.let {
|
||||||
try {
|
try {
|
||||||
_ordering.value = RevoltJson.decodeFromString(
|
_ordering.value = StoatJson.decodeFromString(
|
||||||
OrderingSettings.serializer(),
|
OrderingSettings.serializer(),
|
||||||
it.value
|
it.value
|
||||||
)
|
)
|
||||||
|
|
@ -59,7 +59,7 @@ object SyncedSettings {
|
||||||
|
|
||||||
settings["android"]?.let {
|
settings["android"]?.let {
|
||||||
try {
|
try {
|
||||||
_android.value = RevoltJson.decodeFromString(
|
_android.value = StoatJson.decodeFromString(
|
||||||
AndroidSpecificSettings.serializer(),
|
AndroidSpecificSettings.serializer(),
|
||||||
it.value
|
it.value
|
||||||
)
|
)
|
||||||
|
|
@ -82,7 +82,7 @@ object SyncedSettings {
|
||||||
private fun parseNotificationSettings(value: String): NotificationSettings {
|
private fun parseNotificationSettings(value: String): NotificationSettings {
|
||||||
return try {
|
return try {
|
||||||
var intermediate =
|
var intermediate =
|
||||||
RevoltJson.decodeFromString(_NotificationSettingsToParse.serializer(), value)
|
StoatJson.decodeFromString(_NotificationSettingsToParse.serializer(), value)
|
||||||
|
|
||||||
// Throw out any value of intermediate.server and .channel that isn't a string
|
// Throw out any value of intermediate.server and .channel that isn't a string
|
||||||
intermediate = intermediate.copy(
|
intermediate = intermediate.copy(
|
||||||
|
|
@ -108,23 +108,23 @@ object SyncedSettings {
|
||||||
|
|
||||||
suspend fun updateOrdering(value: OrderingSettings) {
|
suspend fun updateOrdering(value: OrderingSettings) {
|
||||||
_ordering.value = value
|
_ordering.value = value
|
||||||
setKey("ordering", RevoltJson.encodeToString(OrderingSettings.serializer(), value))
|
setKey("ordering", StoatJson.encodeToString(OrderingSettings.serializer(), value))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateAndroid(value: AndroidSpecificSettings) {
|
suspend fun updateAndroid(value: AndroidSpecificSettings) {
|
||||||
_android.value = value
|
_android.value = value
|
||||||
setKey("android", RevoltJson.encodeToString(AndroidSpecificSettings.serializer(), value))
|
setKey("android", StoatJson.encodeToString(AndroidSpecificSettings.serializer(), value))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateNotifications(value: NotificationSettings) {
|
suspend fun updateNotifications(value: NotificationSettings) {
|
||||||
_notifications.value = value
|
_notifications.value = value
|
||||||
setKey("notifications", RevoltJson.encodeToString(NotificationSettings.serializer(), value))
|
setKey("notifications", StoatJson.encodeToString(NotificationSettings.serializer(), value))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun resetOrdering() {
|
suspend fun resetOrdering() {
|
||||||
val default = OrderingSettings()
|
val default = OrderingSettings()
|
||||||
_ordering.value = default
|
_ordering.value = default
|
||||||
setKey("ordering", RevoltJson.encodeToString(OrderingSettings.serializer(), default))
|
setKey("ordering", StoatJson.encodeToString(OrderingSettings.serializer(), default))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun resetAndroid() {
|
suspend fun resetAndroid() {
|
||||||
|
|
@ -134,7 +134,7 @@ object SyncedSettings {
|
||||||
messageReplyStyle = "None"
|
messageReplyStyle = "None"
|
||||||
)
|
)
|
||||||
_android.value = default
|
_android.value = default
|
||||||
setKey("android", RevoltJson.encodeToString(AndroidSpecificSettings.serializer(), default))
|
setKey("android", StoatJson.encodeToString(AndroidSpecificSettings.serializer(), default))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun resetNotifications() {
|
suspend fun resetNotifications() {
|
||||||
|
|
@ -142,7 +142,7 @@ object SyncedSettings {
|
||||||
_notifications.value = default
|
_notifications.value = default
|
||||||
setKey(
|
setKey(
|
||||||
"notifications",
|
"notifications",
|
||||||
RevoltJson.encodeToString(NotificationSettings.serializer(), default)
|
StoatJson.encodeToString(NotificationSettings.serializer(), default)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
package chat.revolt.api.unreads
|
package chat.stoat.api.unreads
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.runtime.mutableStateMapOf
|
import androidx.compose.runtime.mutableStateMapOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.internals.ULID
|
import chat.stoat.api.internals.ULID
|
||||||
import chat.revolt.api.routes.channel.ackChannel
|
import chat.stoat.api.routes.channel.ackChannel
|
||||||
import chat.revolt.api.routes.server.ackServer
|
import chat.stoat.api.routes.server.ackServer
|
||||||
import chat.revolt.api.routes.sync.syncUnreads
|
import chat.stoat.api.routes.sync.syncUnreads
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.stoat.api.schemas.ChannelType
|
||||||
import chat.revolt.api.schemas.ChannelUnread
|
import chat.stoat.api.schemas.ChannelUnread
|
||||||
import chat.revolt.api.settings.NotificationSettingsProvider
|
import chat.stoat.api.settings.NotificationSettingsProvider
|
||||||
|
|
||||||
class Unreads {
|
class Unreads {
|
||||||
private val hasLoaded = mutableStateOf(false)
|
private val hasLoaded = mutableStateOf(false)
|
||||||
|
|
@ -50,8 +50,8 @@ class Unreads {
|
||||||
fun serverHasUnread(serverId: String): Boolean {
|
fun serverHasUnread(serverId: String): Boolean {
|
||||||
if (!hasLoaded.value) return false
|
if (!hasLoaded.value) return false
|
||||||
|
|
||||||
return RevoltAPI.serverCache[serverId]?.channels?.any {
|
return StoatAPI.serverCache[serverId]?.channels?.any {
|
||||||
val channel = RevoltAPI.channelCache[it] ?: return@any false // Channel not found
|
val channel = StoatAPI.channelCache[it] ?: return@any false // Channel not found
|
||||||
if (channel.channelType == ChannelType.VoiceChannel) return@any false // Channel is voice
|
if (channel.channelType == ChannelType.VoiceChannel) return@any false // Channel is voice
|
||||||
if (NotificationSettingsProvider.isChannelMuted(
|
if (NotificationSettingsProvider.isChannelMuted(
|
||||||
it,
|
it,
|
||||||
|
|
@ -81,7 +81,7 @@ class Unreads {
|
||||||
suspend fun markServerAsRead(serverId: String, sync: Boolean = true) {
|
suspend fun markServerAsRead(serverId: String, sync: Boolean = true) {
|
||||||
if (!hasLoaded.value) return
|
if (!hasLoaded.value) return
|
||||||
|
|
||||||
val server = RevoltAPI.serverCache[serverId] ?: return
|
val server = StoatAPI.serverCache[serverId] ?: return
|
||||||
server.channels?.forEach { channel ->
|
server.channels?.forEach { channel ->
|
||||||
channels[channel] = channels[channel]?.copy(last_id = ULID.makeNext()) ?: ChannelUnread(
|
channels[channel] = channels[channel]?.copy(last_id = ULID.makeNext()) ?: ChannelUnread(
|
||||||
channel,
|
channel,
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package chat.revolt.c2dm
|
package chat.stoat.c2dm
|
||||||
|
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationChannelGroup
|
import android.app.NotificationChannelGroup
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.content.ContextCompat.getSystemService
|
import androidx.core.content.ContextCompat.getSystemService
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// * Add the remaining groups.
|
// * Add the remaining groups.
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.c2dm
|
package chat.stoat.c2dm
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
|
@ -10,17 +10,17 @@ import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.app.Person
|
import androidx.core.app.Person
|
||||||
import androidx.core.app.RemoteInput
|
import androidx.core.app.RemoteInput
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.activities.MainActivity
|
import chat.stoat.activities.MainActivity
|
||||||
import chat.revolt.api.REVOLT_BASE
|
import chat.stoat.api.STOAT_BASE
|
||||||
import chat.revolt.api.RevoltJson
|
import chat.stoat.api.StoatJson
|
||||||
import chat.revolt.api.internals.ULID
|
import chat.stoat.api.internals.ULID
|
||||||
import chat.revolt.api.routes.push.subscribePush
|
import chat.stoat.api.routes.push.subscribePush
|
||||||
import chat.revolt.api.schemas.Message
|
import chat.stoat.api.schemas.Message
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
import chat.revolt.c2dm.ChannelRegistrator.Companion.CHANNEL_ID_GROUP_SOCIAL_FRIENDREQUESTS
|
import chat.stoat.c2dm.ChannelRegistrator.Companion.CHANNEL_ID_GROUP_SOCIAL_FRIENDREQUESTS
|
||||||
import chat.revolt.persistence.Database
|
import chat.stoat.persistence.Database
|
||||||
import chat.revolt.persistence.SqlStorage
|
import chat.stoat.persistence.SqlStorage
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService
|
import com.google.firebase.messaging.FirebaseMessagingService
|
||||||
import com.google.firebase.messaging.RemoteMessage
|
import com.google.firebase.messaging.RemoteMessage
|
||||||
|
|
@ -51,13 +51,13 @@ class HandlerService : FirebaseMessagingService() {
|
||||||
|
|
||||||
Log.d("HandlerService", payloadString)
|
Log.d("HandlerService", payloadString)
|
||||||
|
|
||||||
val payload = RevoltJson.parseToJsonElement(payloadString).jsonObject
|
val payload = StoatJson.parseToJsonElement(payloadString).jsonObject
|
||||||
val keys = payload.keys.toList().toString()
|
val keys = payload.keys.toList().toString()
|
||||||
Log.d("HandlerService", "following keys: $keys")
|
Log.d("HandlerService", "following keys: $keys")
|
||||||
|
|
||||||
var authorIcon = payload["icon"]?.jsonPrimitive?.contentOrNull
|
var authorIcon = payload["icon"]?.jsonPrimitive?.contentOrNull
|
||||||
val message = payload["message"]?.jsonObject?.let {
|
val message = payload["message"]?.jsonObject?.let {
|
||||||
RevoltJson.decodeFromJsonElement(
|
StoatJson.decodeFromJsonElement(
|
||||||
Message.serializer(),
|
Message.serializer(),
|
||||||
it
|
it
|
||||||
)
|
)
|
||||||
|
|
@ -67,7 +67,7 @@ class HandlerService : FirebaseMessagingService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val user = payload["message"]?.jsonObject?.get("user")?.jsonObject?.let {
|
val user = payload["message"]?.jsonObject?.get("user")?.jsonObject?.let {
|
||||||
RevoltJson.decodeFromJsonElement(
|
StoatJson.decodeFromJsonElement(
|
||||||
User.serializer(),
|
User.serializer(),
|
||||||
it
|
it
|
||||||
)
|
)
|
||||||
|
|
@ -78,7 +78,7 @@ class HandlerService : FirebaseMessagingService() {
|
||||||
|
|
||||||
if (authorIcon == null) {
|
if (authorIcon == null) {
|
||||||
authorIcon =
|
authorIcon =
|
||||||
"$REVOLT_BASE/users/${message.author?.ifBlank { "0".repeat(26) }}/default_avatar"
|
"$STOAT_BASE/users/${message.author?.ifBlank { "0".repeat(26) }}/default_avatar"
|
||||||
}
|
}
|
||||||
|
|
||||||
val db = Database(SqlStorage.driver)
|
val db = Database(SqlStorage.driver)
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package chat.revolt.callbacks
|
package chat.stoat.callbacks
|
||||||
|
|
||||||
import chat.revolt.screens.chat.ChatRouterDestination
|
import chat.stoat.screens.chat.ChatRouterDestination
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
|
||||||
sealed class Action {
|
sealed class Action {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.callbacks
|
package chat.stoat.callbacks
|
||||||
|
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import android.icu.text.DateFormat
|
import android.icu.text.DateFormat
|
||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
|
@ -28,10 +28,10 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.api.realtime.DisconnectionState
|
import chat.stoat.api.realtime.DisconnectionState
|
||||||
import chat.revolt.api.settings.LoadedSettings
|
import chat.stoat.api.settings.LoadedSettings
|
||||||
import chat.revolt.ui.theme.Theme
|
import chat.stoat.ui.theme.Theme
|
||||||
|
|
||||||
private val NON_MATERIAL_COLOURS = mapOf(
|
private val NON_MATERIAL_COLOURS = mapOf(
|
||||||
DisconnectionState.Disconnected to (Color(0xff4E0C0C) to Color(0xffff1744)),
|
DisconnectionState.Disconnected to (Color(0xff4E0C0C) to Color(0xffff1744)),
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
|
@ -23,14 +23,14 @@ import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import chat.revolt.api.internals.BrushCompat
|
import chat.stoat.api.internals.BrushCompat
|
||||||
import chat.revolt.api.internals.solidColor
|
import chat.stoat.api.internals.solidColor
|
||||||
import chat.revolt.api.routes.microservices.january.asJanuaryProxyUrl
|
import chat.stoat.api.routes.microservices.january.asJanuaryProxyUrl
|
||||||
import chat.revolt.api.schemas.Embed
|
import chat.stoat.api.schemas.Embed
|
||||||
import chat.revolt.composables.chat.specialembeds.SpecialEmbedSwitch
|
import chat.stoat.composables.chat.specialembeds.SpecialEmbedSwitch
|
||||||
import chat.revolt.composables.generic.RemoteImage
|
import chat.stoat.composables.generic.RemoteImage
|
||||||
import chat.revolt.composables.markdown.RichMarkdown
|
import chat.stoat.composables.markdown.RichMarkdown
|
||||||
import chat.revolt.api.schemas.Embed as EmbedSchema
|
import chat.stoat.api.schemas.Embed as EmbedSchema
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RegularEmbed(
|
fun RegularEmbed(
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
|
@ -26,16 +26,16 @@ import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.internals.solidColor
|
import chat.stoat.api.internals.solidColor
|
||||||
import chat.revolt.api.routes.channel.fetchSingleMessage
|
import chat.stoat.api.routes.channel.fetchSingleMessage
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
import chat.revolt.api.settings.Experiments
|
import chat.stoat.api.settings.Experiments
|
||||||
import chat.revolt.composables.generic.UserAvatar
|
import chat.stoat.composables.generic.UserAvatar
|
||||||
import chat.revolt.markdown.jbm.JBM
|
import chat.stoat.markdown.jbm.JBM
|
||||||
import chat.revolt.markdown.jbm.JBMRenderer
|
import chat.stoat.markdown.jbm.JBMRenderer
|
||||||
import chat.revolt.markdown.jbm.LocalJBMarkdownTreeState
|
import chat.stoat.markdown.jbm.LocalJBMarkdownTreeState
|
||||||
import java.util.concurrent.CancellationException
|
import java.util.concurrent.CancellationException
|
||||||
|
|
||||||
@OptIn(JBM::class)
|
@OptIn(JBM::class)
|
||||||
|
|
@ -47,8 +47,8 @@ fun InReplyTo(
|
||||||
withMention: Boolean = false,
|
withMention: Boolean = false,
|
||||||
onMessageClick: (String) -> Unit = { _ -> }
|
onMessageClick: (String) -> Unit = { _ -> }
|
||||||
) {
|
) {
|
||||||
val message = RevoltAPI.messageCache[messageId]
|
val message = StoatAPI.messageCache[messageId]
|
||||||
val author = RevoltAPI.userCache[message?.author ?: ""]
|
val author = StoatAPI.userCache[message?.author ?: ""]
|
||||||
|
|
||||||
val username = message?.let { authorName(it) }
|
val username = message?.let { authorName(it) }
|
||||||
?: author?.let { User.resolveDefaultName(it) }
|
?: author?.let { User.resolveDefaultName(it) }
|
||||||
|
|
@ -58,12 +58,12 @@ fun InReplyTo(
|
||||||
val usernameColor =
|
val usernameColor =
|
||||||
message?.let { authorColour(it) } ?: Brush.solidColor(contentColor)
|
message?.let { authorColour(it) } ?: Brush.solidColor(contentColor)
|
||||||
|
|
||||||
val serverId = remember(channelId) { RevoltAPI.channelCache[channelId]?.server }
|
val serverId = remember(channelId) { StoatAPI.channelCache[channelId]?.server }
|
||||||
|
|
||||||
LaunchedEffect(messageId) {
|
LaunchedEffect(messageId) {
|
||||||
if (messageId !in RevoltAPI.messageCache) {
|
if (messageId !in StoatAPI.messageCache) {
|
||||||
try {
|
try {
|
||||||
RevoltAPI.messageCache[messageId] = fetchSingleMessage(channelId, messageId)
|
StoatAPI.messageCache[messageId] = fetchSingleMessage(channelId, messageId)
|
||||||
} catch (e: CancellationException) {
|
} catch (e: CancellationException) {
|
||||||
// It's fine
|
// It's fine
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
|
@ -9,7 +9,7 @@ import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
|
|
||||||
enum class InlineBadge {
|
enum class InlineBadge {
|
||||||
Bot,
|
Bot,
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
import androidx.compose.material3.LocalContentColor
|
import androidx.compose.material3.LocalContentColor
|
||||||
|
|
@ -8,15 +8,15 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.stoat.api.STOAT_FILES
|
||||||
import chat.revolt.api.internals.BrushCompat
|
import chat.stoat.api.internals.BrushCompat
|
||||||
import chat.revolt.api.internals.Roles
|
import chat.stoat.api.internals.Roles
|
||||||
import chat.revolt.api.internals.solidColor
|
import chat.stoat.api.internals.solidColor
|
||||||
import chat.revolt.api.schemas.Member
|
import chat.stoat.api.schemas.Member
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
import chat.revolt.composables.generic.UserAvatar
|
import chat.stoat.composables.generic.UserAvatar
|
||||||
import chat.revolt.composables.generic.presenceFromStatus
|
import chat.stoat.composables.generic.presenceFromStatus
|
||||||
import chat.revolt.internals.extensions.TransparentListItemColours
|
import chat.stoat.internals.extensions.TransparentListItemColours
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MemberListItem(
|
fun MemberListItem(
|
||||||
|
|
@ -74,7 +74,7 @@ fun MemberListItem(
|
||||||
?: user?.id
|
?: user?.id
|
||||||
?: userId,
|
?: userId,
|
||||||
avatar = user?.avatar,
|
avatar = user?.avatar,
|
||||||
rawUrl = member?.avatar?.let { "$REVOLT_FILES/avatars/${it.id}" },
|
rawUrl = member?.avatar?.let { "$STOAT_FILES/avatars/${it.id}" },
|
||||||
userId = userId,
|
userId = userId,
|
||||||
presence = presenceFromStatus(
|
presence = presenceFromStatus(
|
||||||
user?.status?.presence,
|
user?.status?.presence,
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
|
@ -59,41 +59,41 @@ import androidx.compose.ui.text.style.TextDecoration
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.activities.media.ImageViewActivity
|
import chat.stoat.activities.media.ImageViewActivity
|
||||||
import chat.revolt.activities.media.VideoViewActivity
|
import chat.stoat.activities.media.VideoViewActivity
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.stoat.api.STOAT_FILES
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.internals.BrushCompat
|
import chat.stoat.api.internals.BrushCompat
|
||||||
import chat.revolt.api.internals.MessageFlag
|
import chat.stoat.api.internals.MessageFlag
|
||||||
import chat.revolt.api.internals.Roles
|
import chat.stoat.api.internals.Roles
|
||||||
import chat.revolt.api.internals.SpecialUsers
|
import chat.stoat.api.internals.SpecialUsers
|
||||||
import chat.revolt.api.internals.ULID
|
import chat.stoat.api.internals.ULID
|
||||||
import chat.revolt.api.internals.has
|
import chat.stoat.api.internals.has
|
||||||
import chat.revolt.api.internals.solidColor
|
import chat.stoat.api.internals.solidColor
|
||||||
import chat.revolt.api.routes.channel.react
|
import chat.stoat.api.routes.channel.react
|
||||||
import chat.revolt.api.routes.channel.unreact
|
import chat.stoat.api.routes.channel.unreact
|
||||||
import chat.revolt.api.routes.microservices.january.asJanuaryProxyUrl
|
import chat.stoat.api.routes.microservices.january.asJanuaryProxyUrl
|
||||||
import chat.revolt.api.schemas.AutumnResource
|
import chat.stoat.api.schemas.AutumnResource
|
||||||
import chat.revolt.api.schemas.User
|
import chat.stoat.api.schemas.User
|
||||||
import chat.revolt.api.settings.Experiments
|
import chat.stoat.api.settings.Experiments
|
||||||
import chat.revolt.api.settings.LoadedSettings
|
import chat.stoat.api.settings.LoadedSettings
|
||||||
import chat.revolt.api.settings.MessageReplyStyle
|
import chat.stoat.api.settings.MessageReplyStyle
|
||||||
import chat.revolt.callbacks.Action
|
import chat.stoat.callbacks.Action
|
||||||
import chat.revolt.callbacks.ActionChannel
|
import chat.stoat.callbacks.ActionChannel
|
||||||
import chat.revolt.composables.generic.RemoteImage
|
import chat.stoat.composables.generic.RemoteImage
|
||||||
import chat.revolt.composables.generic.UserAvatar
|
import chat.stoat.composables.generic.UserAvatar
|
||||||
import chat.revolt.composables.generic.UserAvatarWidthPlaceholder
|
import chat.stoat.composables.generic.UserAvatarWidthPlaceholder
|
||||||
import chat.revolt.composables.markdown.LocalMarkdownTreeConfig
|
import chat.stoat.composables.markdown.LocalMarkdownTreeConfig
|
||||||
import chat.revolt.composables.markdown.RichMarkdown
|
import chat.stoat.composables.markdown.RichMarkdown
|
||||||
import chat.revolt.internals.text.Gigamoji
|
import chat.stoat.internals.text.Gigamoji
|
||||||
import chat.revolt.internals.text.MessageProcessor
|
import chat.stoat.internals.text.MessageProcessor
|
||||||
import chat.revolt.markdown.jbm.JBM
|
import chat.stoat.markdown.jbm.JBM
|
||||||
import chat.revolt.markdown.jbm.JBMRenderer
|
import chat.stoat.markdown.jbm.JBMRenderer
|
||||||
import chat.revolt.markdown.jbm.LocalJBMarkdownTreeState
|
import chat.stoat.markdown.jbm.LocalJBMarkdownTreeState
|
||||||
import chat.revolt.persistence.KVStorage
|
import chat.stoat.persistence.KVStorage
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import chat.revolt.api.schemas.Message as MessageSchema
|
import chat.stoat.api.schemas.Message as MessageSchema
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun authorColour(message: MessageSchema): Brush {
|
fun authorColour(message: MessageSchema): Brush {
|
||||||
|
|
@ -102,7 +102,7 @@ fun authorColour(message: MessageSchema): Brush {
|
||||||
} else {
|
} else {
|
||||||
val defaultColour = Brush.solidColor(LocalContentColor.current)
|
val defaultColour = Brush.solidColor(LocalContentColor.current)
|
||||||
|
|
||||||
val serverId = RevoltAPI.channelCache[message.channel]?.server ?: return defaultColour
|
val serverId = StoatAPI.channelCache[message.channel]?.server ?: return defaultColour
|
||||||
|
|
||||||
val highestRole = message.author?.let {
|
val highestRole = message.author?.let {
|
||||||
Roles.resolveHighestRole(serverId, it, withColour = true)
|
Roles.resolveHighestRole(serverId, it, withColour = true)
|
||||||
|
|
@ -120,14 +120,14 @@ fun authorName(message: MessageSchema): String {
|
||||||
}
|
}
|
||||||
|
|
||||||
val serverId =
|
val serverId =
|
||||||
RevoltAPI.channelCache[message.channel]?.server
|
StoatAPI.channelCache[message.channel]?.server
|
||||||
?: return RevoltAPI.userCache[message.author]?.let { User.resolveDefaultName(it) }
|
?: return StoatAPI.userCache[message.author]?.let { User.resolveDefaultName(it) }
|
||||||
?: stringResource(R.string.unknown)
|
?: stringResource(R.string.unknown)
|
||||||
|
|
||||||
val member = message.author?.let { RevoltAPI.members.getMember(serverId, it) }
|
val member = message.author?.let { StoatAPI.members.getMember(serverId, it) }
|
||||||
?: return stringResource(R.string.unknown)
|
?: return stringResource(R.string.unknown)
|
||||||
return member.nickname
|
return member.nickname
|
||||||
?: RevoltAPI.userCache[message.author]?.let { User.resolveDefaultName(it) }
|
?: StoatAPI.userCache[message.author]?.let { User.resolveDefaultName(it) }
|
||||||
?: stringResource(R.string.unknown)
|
?: stringResource(R.string.unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,11 +138,11 @@ fun authorAvatarUrl(message: MessageSchema): String? {
|
||||||
}
|
}
|
||||||
|
|
||||||
val serverId =
|
val serverId =
|
||||||
RevoltAPI.channelCache[message.channel]?.server ?: return null
|
StoatAPI.channelCache[message.channel]?.server ?: return null
|
||||||
val member = message.author?.let { RevoltAPI.members.getMember(serverId, it) }
|
val member = message.author?.let { StoatAPI.members.getMember(serverId, it) }
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
return member.avatar?.let { "$REVOLT_FILES/avatars/${it.id}" }
|
return member.avatar?.let { "$STOAT_FILES/avatars/${it.id}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun viewUrlInBrowser(ctx: android.content.Context, url: String) {
|
fun viewUrlInBrowser(ctx: android.content.Context, url: String) {
|
||||||
|
|
@ -153,7 +153,7 @@ fun viewUrlInBrowser(ctx: android.content.Context, url: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun viewAttachmentInBrowser(ctx: android.content.Context, attachment: AutumnResource) {
|
fun viewAttachmentInBrowser(ctx: android.content.Context, attachment: AutumnResource) {
|
||||||
val url = "$REVOLT_FILES/attachments/${attachment.id}/${attachment.filename}"
|
val url = "$STOAT_FILES/attachments/${attachment.id}/${attachment.filename}"
|
||||||
viewUrlInBrowser(ctx, url)
|
viewUrlInBrowser(ctx, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,7 +198,7 @@ fun Message(
|
||||||
webhookName: String? = null,
|
webhookName: String? = null,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val author = RevoltAPI.userCache[message.author] ?: return CircularProgressIndicator()
|
val author = StoatAPI.userCache[message.author] ?: return CircularProgressIndicator()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
@ -230,8 +230,8 @@ fun Message(
|
||||||
var mentionsSelfRole by remember(message) { mutableStateOf(false) }
|
var mentionsSelfRole by remember(message) { mutableStateOf(false) }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
val serverId =
|
val serverId =
|
||||||
RevoltAPI.channelCache[message.channel]?.server ?: return@LaunchedEffect
|
StoatAPI.channelCache[message.channel]?.server ?: return@LaunchedEffect
|
||||||
var selfMember = RevoltAPI.selfId?.let { RevoltAPI.members.getMember(serverId, it) }
|
var selfMember = StoatAPI.selfId?.let { StoatAPI.members.getMember(serverId, it) }
|
||||||
?: return@LaunchedEffect
|
?: return@LaunchedEffect
|
||||||
var messageRoleMentions = MessageProcessor.findMentionedRoleIDs(message.content)
|
var messageRoleMentions = MessageProcessor.findMentionedRoleIDs(message.content)
|
||||||
|
|
||||||
|
|
@ -281,7 +281,7 @@ fun Message(
|
||||||
} else {
|
} else {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.then(
|
modifier = Modifier.then(
|
||||||
if ((message.mentions?.contains(RevoltAPI.selfId) == true)
|
if ((message.mentions?.contains(StoatAPI.selfId) == true)
|
||||||
|| mentionsSelfRole
|
|| mentionsSelfRole
|
||||||
|| message.flags has MessageFlag.MentionsOnline
|
|| message.flags has MessageFlag.MentionsOnline
|
||||||
|| message.flags has MessageFlag.MentionsEveryone
|
|| message.flags has MessageFlag.MentionsEveryone
|
||||||
|
|
@ -295,7 +295,7 @@ fun Message(
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
message.replies?.forEach { reply ->
|
message.replies?.forEach { reply ->
|
||||||
val replyMessage = RevoltAPI.messageCache[reply]
|
val replyMessage = StoatAPI.messageCache[reply]
|
||||||
|
|
||||||
message.channel?.let { chId ->
|
message.channel?.let { chId ->
|
||||||
InReplyTo(
|
InReplyTo(
|
||||||
|
|
@ -431,7 +431,7 @@ fun Message(
|
||||||
if (Experiments.useKotlinBasedMarkdownRenderer.isEnabled) {
|
if (Experiments.useKotlinBasedMarkdownRenderer.isEnabled) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalJBMarkdownTreeState provides LocalJBMarkdownTreeState.current.copy(
|
LocalJBMarkdownTreeState provides LocalJBMarkdownTreeState.current.copy(
|
||||||
currentServer = RevoltAPI.channelCache[message.channel]?.server,
|
currentServer = StoatAPI.channelCache[message.channel]?.server,
|
||||||
fontSizeMultiplier = Gigamoji.useGigamojiForMessage(
|
fontSizeMultiplier = Gigamoji.useGigamojiForMessage(
|
||||||
message.content
|
message.content
|
||||||
)
|
)
|
||||||
|
|
@ -446,7 +446,7 @@ fun Message(
|
||||||
} else {
|
} else {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalMarkdownTreeConfig provides LocalMarkdownTreeConfig.current.copy(
|
LocalMarkdownTreeConfig provides LocalMarkdownTreeConfig.current.copy(
|
||||||
currentServer = RevoltAPI.channelCache[message.channel]?.server,
|
currentServer = StoatAPI.channelCache[message.channel]?.server,
|
||||||
fontSizeMultiplier = Gigamoji.useGigamojiForMessage(
|
fontSizeMultiplier = Gigamoji.useGigamojiForMessage(
|
||||||
message.content
|
message.content
|
||||||
)
|
)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
|
|
@ -32,11 +32,11 @@ import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.stoat.api.STOAT_FILES
|
||||||
import chat.revolt.api.schemas.AutumnResource
|
import chat.stoat.api.schemas.AutumnResource
|
||||||
import chat.revolt.composables.generic.RemoteImage
|
import chat.stoat.composables.generic.RemoteImage
|
||||||
import chat.revolt.composables.media.AudioPlayer
|
import chat.stoat.composables.media.AudioPlayer
|
||||||
import dev.chrisbanes.haze.hazeEffect
|
import dev.chrisbanes.haze.hazeEffect
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
|
|
@ -83,7 +83,7 @@ fun FileAttachment(attachment: AutumnResource) {
|
||||||
@SuppressLint("UnusedBoxWithConstraintsScope")
|
@SuppressLint("UnusedBoxWithConstraintsScope")
|
||||||
@Composable
|
@Composable
|
||||||
fun ImageAttachment(attachment: AutumnResource) {
|
fun ImageAttachment(attachment: AutumnResource) {
|
||||||
val url = "$REVOLT_FILES/attachments/${attachment.id}/${attachment.filename}"
|
val url = "$STOAT_FILES/attachments/${attachment.id}/${attachment.filename}"
|
||||||
var spoilerShown by remember { mutableStateOf(false) }
|
var spoilerShown by remember { mutableStateOf(false) }
|
||||||
val hazeState =
|
val hazeState =
|
||||||
if (attachment.filename?.startsWith("SPOILER_") == true) rememberHazeState() else null
|
if (attachment.filename?.startsWith("SPOILER_") == true) rememberHazeState() else null
|
||||||
|
|
@ -149,7 +149,7 @@ fun VideoPlayButton() {
|
||||||
@SuppressLint("UnusedBoxWithConstraintsScope")
|
@SuppressLint("UnusedBoxWithConstraintsScope")
|
||||||
@Composable
|
@Composable
|
||||||
fun VideoAttachment(attachment: AutumnResource) {
|
fun VideoAttachment(attachment: AutumnResource) {
|
||||||
val url = "$REVOLT_FILES/attachments/${attachment.id}/${attachment.filename}"
|
val url = "$STOAT_FILES/attachments/${attachment.id}/${attachment.filename}"
|
||||||
|
|
||||||
BoxWithConstraints {
|
BoxWithConstraints {
|
||||||
Box(
|
Box(
|
||||||
|
|
@ -179,7 +179,7 @@ fun VideoAttachment(attachment: AutumnResource) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AudioAttachment(attachment: AutumnResource) {
|
fun AudioAttachment(attachment: AutumnResource) {
|
||||||
val url = "$REVOLT_FILES/attachments/${attachment.id}/${attachment.filename}"
|
val url = "$STOAT_FILES/attachments/${attachment.id}/${attachment.filename}"
|
||||||
AudioPlayer(
|
AudioPlayer(
|
||||||
url = url,
|
url = url,
|
||||||
filename = attachment.filename ?: "Audio",
|
filename = attachment.filename ?: "Audio",
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
|
@ -79,17 +79,17 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.IntSize
|
import androidx.compose.ui.unit.IntSize
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import chat.revolt.R
|
import chat.stoat.R
|
||||||
import chat.revolt.activities.RevoltTweenFloat
|
import chat.stoat.activities.StoatTweenFloat
|
||||||
import chat.revolt.activities.RevoltTweenInt
|
import chat.stoat.activities.StoatTweenInt
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.stoat.api.STOAT_FILES
|
||||||
import chat.revolt.api.internals.BrushCompat
|
import chat.stoat.api.internals.BrushCompat
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.stoat.api.schemas.ChannelType
|
||||||
import chat.revolt.api.schemas.Member
|
import chat.stoat.api.schemas.Member
|
||||||
import chat.revolt.composables.generic.RemoteImage
|
import chat.stoat.composables.generic.RemoteImage
|
||||||
import chat.revolt.composables.generic.UserAvatar
|
import chat.stoat.composables.generic.UserAvatar
|
||||||
import chat.revolt.composables.screens.chat.ChannelIcon
|
import chat.stoat.composables.screens.chat.ChannelIcon
|
||||||
import chat.revolt.internals.Autocomplete
|
import chat.stoat.internals.Autocomplete
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
fun Pair<Int, Int>.asTextRange(): TextRange {
|
fun Pair<Int, Int>.asTextRange(): TextRange {
|
||||||
|
|
@ -111,25 +111,25 @@ private fun CharSequence.lastWordStartsAt(): Int {
|
||||||
|
|
||||||
sealed class AutocompleteSuggestion {
|
sealed class AutocompleteSuggestion {
|
||||||
data class User(
|
data class User(
|
||||||
val user: chat.revolt.api.schemas.User,
|
val user: chat.stoat.api.schemas.User,
|
||||||
val member: Member?,
|
val member: Member?,
|
||||||
val query: String
|
val query: String
|
||||||
) : AutocompleteSuggestion()
|
) : AutocompleteSuggestion()
|
||||||
|
|
||||||
data class Channel(
|
data class Channel(
|
||||||
val channel: chat.revolt.api.schemas.Channel,
|
val channel: chat.stoat.api.schemas.Channel,
|
||||||
val query: String
|
val query: String
|
||||||
) : AutocompleteSuggestion()
|
) : AutocompleteSuggestion()
|
||||||
|
|
||||||
data class Emoji(
|
data class Emoji(
|
||||||
val shortcode: String,
|
val shortcode: String,
|
||||||
val unicode: String?,
|
val unicode: String?,
|
||||||
val custom: chat.revolt.api.schemas.Emoji?,
|
val custom: chat.stoat.api.schemas.Emoji?,
|
||||||
val query: String
|
val query: String
|
||||||
) : AutocompleteSuggestion()
|
) : AutocompleteSuggestion()
|
||||||
|
|
||||||
data class Role(
|
data class Role(
|
||||||
val role: chat.revolt.api.schemas.Role,
|
val role: chat.stoat.api.schemas.Role,
|
||||||
val id: String,
|
val id: String,
|
||||||
val query: String
|
val query: String
|
||||||
) : AutocompleteSuggestion()
|
) : AutocompleteSuggestion()
|
||||||
|
|
@ -318,7 +318,7 @@ fun MessageField(
|
||||||
userId = item.user.id ?: "",
|
userId = item.user.id ?: "",
|
||||||
avatar = item.user.avatar,
|
avatar = item.user.avatar,
|
||||||
rawUrl = item.member?.avatar?.id?.let {
|
rawUrl = item.member?.avatar?.id?.let {
|
||||||
"$REVOLT_FILES/avatars/$it"
|
"$STOAT_FILES/avatars/$it"
|
||||||
},
|
},
|
||||||
size = SuggestionChipDefaults.IconSize,
|
size = SuggestionChipDefaults.IconSize,
|
||||||
)
|
)
|
||||||
|
|
@ -444,7 +444,7 @@ fun MessageField(
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
RemoteImage(
|
RemoteImage(
|
||||||
url = "$REVOLT_FILES/emojis/${item.custom?.id}",
|
url = "$STOAT_FILES/emojis/${item.custom?.id}",
|
||||||
description = null,
|
description = null,
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -606,18 +606,18 @@ fun MessageField(
|
||||||
full.height
|
full.height
|
||||||
)
|
)
|
||||||
}) + slideInHorizontally(
|
}) + slideInHorizontally(
|
||||||
animationSpec = RevoltTweenInt,
|
animationSpec = StoatTweenInt,
|
||||||
initialOffsetX = { -it }
|
initialOffsetX = { -it }
|
||||||
) + fadeIn(animationSpec = RevoltTweenFloat),
|
) + fadeIn(animationSpec = StoatTweenFloat),
|
||||||
exit = shrinkOut(targetSize = { full ->
|
exit = shrinkOut(targetSize = { full ->
|
||||||
IntSize(
|
IntSize(
|
||||||
0,
|
0,
|
||||||
full.height
|
full.height
|
||||||
)
|
)
|
||||||
}) + slideOutHorizontally(
|
}) + slideOutHorizontally(
|
||||||
animationSpec = RevoltTweenInt,
|
animationSpec = StoatTweenInt,
|
||||||
targetOffsetX = { it }
|
targetOffsetX = { it }
|
||||||
) + fadeOut(animationSpec = RevoltTweenFloat)
|
) + fadeOut(animationSpec = StoatTweenFloat)
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = when {
|
painter = when {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.animateColorAsState
|
import androidx.compose.animation.animateColorAsState
|
||||||
|
|
@ -28,10 +28,10 @@ import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.stoat.api.STOAT_FILES
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.stoat.api.StoatAPI
|
||||||
import chat.revolt.api.internals.isUlid
|
import chat.stoat.api.internals.isUlid
|
||||||
import chat.revolt.composables.generic.RemoteImage
|
import chat.stoat.composables.generic.RemoteImage
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -41,7 +41,7 @@ fun Reaction(
|
||||||
onClick: (Boolean) -> Unit,
|
onClick: (Boolean) -> Unit,
|
||||||
onLongClick: () -> Unit
|
onLongClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
val hasOwn = members.contains(RevoltAPI.selfId)
|
val hasOwn = members.contains(StoatAPI.selfId)
|
||||||
|
|
||||||
val background by animateColorAsState(
|
val background by animateColorAsState(
|
||||||
targetValue = if (hasOwn) {
|
targetValue = if (hasOwn) {
|
||||||
|
|
@ -74,7 +74,7 @@ fun Reaction(
|
||||||
CompositionLocalProvider(LocalContentColor provides foreground) {
|
CompositionLocalProvider(LocalContentColor provides foreground) {
|
||||||
if (emoji.isUlid()) {
|
if (emoji.isUlid()) {
|
||||||
RemoteImage(
|
RemoteImage(
|
||||||
url = "$REVOLT_FILES/emojis/${emoji}",
|
url = "$STOAT_FILES/emojis/${emoji}",
|
||||||
description = null,
|
description = null,
|
||||||
modifier = Modifier.size(16.dp)
|
modifier = Modifier.size(16.dp)
|
||||||
)
|
)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package chat.revolt.composables.chat
|
package chat.stoat.composables.chat
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue