mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-13 05:40:31 +05:30
Merge pull request #326 from Bnyro/shareintent
Open Video/Channel/Playlist Links with LT
This commit is contained in:
commit
4531cd6def
@ -41,100 +41,6 @@
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<!-- youtube -->
|
||||
<intent-filter>
|
||||
<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="youtube.com" />
|
||||
<data android:host="m.youtube.com" />
|
||||
<data android:host="www.youtube.com" />
|
||||
<data android:host="music.youtube.com" />
|
||||
<!-- video prefix -->
|
||||
<data android:pathPrefix="/v/" />
|
||||
<data android:pathPrefix="/embed/" />
|
||||
<data android:pathPrefix="/watch" />
|
||||
<!--<data android:pathPrefix="/attribution_link" />-->
|
||||
<data android:pathPrefix="/shorts/" />
|
||||
<!-- channel prefix -->
|
||||
<data android:pathPrefix="/channel/" />
|
||||
<data android:pathPrefix="/user/" />
|
||||
<data android:pathPrefix="/c/" />
|
||||
<!-- playlist prefix -->
|
||||
<data android:pathPrefix="/playlist" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
|
||||
<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="youtu.be" />
|
||||
<data android:pathPrefix="/" />
|
||||
</intent-filter>
|
||||
<!-- Invidious filter -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
|
||||
<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="tubus.eduvid.org" />
|
||||
<data android:host="invidio.us" />
|
||||
<data android:host="dev.invidio.us" />
|
||||
<data android:host="www.invidio.us" />
|
||||
<data android:host="redirect.invidious.io" />
|
||||
<data android:host="invidious.snopyta.org" />
|
||||
<data android:host="yewtu.be" />
|
||||
<data android:host="tube.connect.cafe" />
|
||||
<data android:host="invidious.kavin.rocks" />
|
||||
<data android:host="invidious-us.kavin.rocks" />
|
||||
<data android:host="invidious.site" />
|
||||
<data android:host="vid.mint.lgbt" />
|
||||
<data android:host="invidiou.site" />
|
||||
<data android:host="invidious.fdn.fr" />
|
||||
<data android:host="invidious.048596.xyz" />
|
||||
<data android:host="invidious.zee.li" />
|
||||
<data android:host="vid.puffyan.us" />
|
||||
<data android:host="ytprivate.com" />
|
||||
<data android:host="invidious.namazso.eu" />
|
||||
<data android:host="invidious.silkky.cloud" />
|
||||
<data android:host="invidious.exonip.de" />
|
||||
<data android:host="inv.riverside.rocks" />
|
||||
<data android:host="invidious.blamefran.net" />
|
||||
<data android:host="invidious.moomoo.me" />
|
||||
<data android:host="ytb.trom.tf" />
|
||||
<data android:host="yt.cyberhost.uk" />
|
||||
<data android:host="y.com.cm" />
|
||||
<data android:pathPrefix="/" />
|
||||
</intent-filter>
|
||||
<!-- Piped filter -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
<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="piped.tokhmi.xyz" />
|
||||
<data android:host="piped.kavin.rocks" />
|
||||
<data android:host="piped.silkky.cloud" />
|
||||
<data android:host="piped.silkky.cloud" />
|
||||
<data android:host="piped.mint.lgbt" />
|
||||
<data android:host="il.ax" />
|
||||
<data android:pathPrefix="/" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity-alias
|
||||
@ -256,6 +162,112 @@
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity
|
||||
android:name=".RouterActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleInstance"
|
||||
>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
<!-- youtube -->
|
||||
<intent-filter>
|
||||
<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="youtube.com" />
|
||||
<data android:host="m.youtube.com" />
|
||||
<data android:host="www.youtube.com" />
|
||||
<data android:host="music.youtube.com" />
|
||||
<!-- video prefix -->
|
||||
<data android:pathPrefix="/v/" />
|
||||
<data android:pathPrefix="/embed/" />
|
||||
<data android:pathPrefix="/watch" />
|
||||
<!--<data android:pathPrefix="/attribution_link" />-->
|
||||
<data android:pathPrefix="/shorts/" />
|
||||
<!-- channel prefix -->
|
||||
<data android:pathPrefix="/channel/" />
|
||||
<data android:pathPrefix="/user/" />
|
||||
<data android:pathPrefix="/c/" />
|
||||
<!-- playlist prefix -->
|
||||
<data android:pathPrefix="/playlist" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
|
||||
<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="youtu.be" />
|
||||
<data android:pathPrefix="/" />
|
||||
</intent-filter>
|
||||
<!-- Invidious filter -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
|
||||
<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="tubus.eduvid.org" />
|
||||
<data android:host="invidio.us" />
|
||||
<data android:host="dev.invidio.us" />
|
||||
<data android:host="www.invidio.us" />
|
||||
<data android:host="redirect.invidious.io" />
|
||||
<data android:host="invidious.snopyta.org" />
|
||||
<data android:host="yewtu.be" />
|
||||
<data android:host="tube.connect.cafe" />
|
||||
<data android:host="invidious.kavin.rocks" />
|
||||
<data android:host="invidious-us.kavin.rocks" />
|
||||
<data android:host="invidious.site" />
|
||||
<data android:host="vid.mint.lgbt" />
|
||||
<data android:host="invidiou.site" />
|
||||
<data android:host="invidious.fdn.fr" />
|
||||
<data android:host="invidious.048596.xyz" />
|
||||
<data android:host="invidious.zee.li" />
|
||||
<data android:host="vid.puffyan.us" />
|
||||
<data android:host="ytprivate.com" />
|
||||
<data android:host="invidious.namazso.eu" />
|
||||
<data android:host="invidious.silkky.cloud" />
|
||||
<data android:host="invidious.exonip.de" />
|
||||
<data android:host="inv.riverside.rocks" />
|
||||
<data android:host="invidious.blamefran.net" />
|
||||
<data android:host="invidious.moomoo.me" />
|
||||
<data android:host="ytb.trom.tf" />
|
||||
<data android:host="yt.cyberhost.uk" />
|
||||
<data android:host="y.com.cm" />
|
||||
<data android:pathPrefix="/" />
|
||||
</intent-filter>
|
||||
<!-- Piped filter -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
<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="piped.tokhmi.xyz" />
|
||||
<data android:host="piped.kavin.rocks" />
|
||||
<data android:host="piped.silkky.cloud" />
|
||||
<data android:host="piped.silkky.cloud" />
|
||||
<data android:host="piped.mint.lgbt" />
|
||||
<data android:host="il.ax" />
|
||||
<data android:pathPrefix="/" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".DownloadService"
|
||||
android:enabled="true"
|
||||
|
@ -142,108 +142,110 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val action: String? = intent?.action
|
||||
val data: Uri? = intent?.data
|
||||
Log.d(TAG, "dafaq" + data.toString())
|
||||
val intentData: Uri? = intent?.data
|
||||
// check whether an URI got submitted over the intent data
|
||||
if (intentData != null && intentData.host != null && intentData.path != null) {
|
||||
Log.d("intentData", "${intentData.host} ${intentData.path} ")
|
||||
// load the URI of the submitted link (e.g. video)
|
||||
loadIntentData(intentData)
|
||||
}
|
||||
}
|
||||
|
||||
if (data != null) {
|
||||
Log.d("dafaq", data.host + " ${data.path} ")
|
||||
if (data.host != null) {
|
||||
if (data.path != null) {
|
||||
// channel
|
||||
if (data.path!!.contains("/channel/") ||
|
||||
data.path!!.contains("/c/") ||
|
||||
data.path!!.contains("/user/")
|
||||
) {
|
||||
var channel = data.path
|
||||
channel = channel!!.replace("/c/", "")
|
||||
channel = channel.replace("/user/", "")
|
||||
val bundle = bundleOf("channel_id" to channel)
|
||||
navController.navigate(R.id.channel, bundle)
|
||||
} else if (data.path!!.contains("/playlist")) {
|
||||
var playlist = data.query!!
|
||||
if (playlist.contains("&")) {
|
||||
var playlists = playlist.split("&")
|
||||
for (v in playlists) {
|
||||
if (v.contains("list=")) {
|
||||
playlist = v
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
playlist = playlist.replace("list=", "")
|
||||
val bundle = bundleOf("playlist_id" to playlist)
|
||||
navController.navigate(R.id.playlistFragment, bundle)
|
||||
} else if (data.path!!.contains("/shorts/") ||
|
||||
data.path!!.contains("/embed/") ||
|
||||
data.path!!.contains("/v/")
|
||||
) {
|
||||
val watch = data.path!!
|
||||
.replace("/shorts/", "")
|
||||
.replace("/v/", "")
|
||||
.replace("/embed/", "")
|
||||
val bundle = Bundle()
|
||||
bundle.putString("videoId", watch)
|
||||
val frag = PlayerFragment()
|
||||
frag.arguments = bundle
|
||||
supportFragmentManager.beginTransaction()
|
||||
.remove(PlayerFragment())
|
||||
.commit()
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, frag)
|
||||
.commitNow()
|
||||
Handler().postDelayed({
|
||||
val motionLayout = findViewById<MotionLayout>(R.id.playerMotionLayout)
|
||||
motionLayout.transitionToEnd()
|
||||
motionLayout.transitionToStart()
|
||||
}, 100)
|
||||
} else if (data.path!!.contains("/watch") && data.query != null) {
|
||||
Log.d("dafaq", data.query!!)
|
||||
var watch = data.query!!
|
||||
if (watch.contains("&")) {
|
||||
var watches = watch.split("&")
|
||||
for (v in watches) {
|
||||
if (v.contains("v=")) {
|
||||
watch = v
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
var bundle = Bundle()
|
||||
bundle.putString("videoId", watch.replace("v=", ""))
|
||||
var frag = PlayerFragment()
|
||||
frag.arguments = bundle
|
||||
supportFragmentManager.beginTransaction()
|
||||
.remove(PlayerFragment())
|
||||
.commit()
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, frag)
|
||||
.commitNow()
|
||||
Handler().postDelayed({
|
||||
val motionLayout = findViewById<MotionLayout>(R.id.playerMotionLayout)
|
||||
motionLayout.transitionToEnd()
|
||||
motionLayout.transitionToStart()
|
||||
}, 100)
|
||||
} else {
|
||||
var watch = data.path!!.replace("/", "")
|
||||
var bundle = Bundle()
|
||||
bundle.putString("videoId", watch)
|
||||
var frag = PlayerFragment()
|
||||
frag.arguments = bundle
|
||||
supportFragmentManager.beginTransaction()
|
||||
.remove(PlayerFragment())
|
||||
.commit()
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, frag)
|
||||
.commitNow()
|
||||
Handler().postDelayed({
|
||||
val motionLayout = findViewById<MotionLayout>(R.id.playerMotionLayout)
|
||||
motionLayout.transitionToEnd()
|
||||
motionLayout.transitionToStart()
|
||||
}, 100)
|
||||
private fun loadIntentData(data: Uri) {
|
||||
// channel
|
||||
if (data.path!!.contains("/channel/") ||
|
||||
data.path!!.contains("/c/") ||
|
||||
data.path!!.contains("/user/")
|
||||
) {
|
||||
Log.i(TAG, "URI Type: Channel")
|
||||
var channel = data.path
|
||||
channel = channel!!.replace("/c/", "")
|
||||
channel = channel.replace("/user/", "")
|
||||
val bundle = bundleOf("channel_id" to channel)
|
||||
navController.navigate(R.id.channel, bundle)
|
||||
} else if (data.path!!.contains("/playlist")) {
|
||||
Log.i(TAG, "URI Type: Playlist")
|
||||
var playlist = data.query!!
|
||||
if (playlist.contains("&")) {
|
||||
var playlists = playlist.split("&")
|
||||
for (v in playlists) {
|
||||
if (v.contains("list=")) {
|
||||
playlist = v
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
playlist = playlist.replace("list=", "")
|
||||
val bundle = bundleOf("playlist_id" to playlist)
|
||||
navController.navigate(R.id.playlistFragment, bundle)
|
||||
} else if (data.path!!.contains("/shorts/") ||
|
||||
data.path!!.contains("/embed/") ||
|
||||
data.path!!.contains("/v/")
|
||||
) {
|
||||
Log.i(TAG, "URI Type: Video")
|
||||
val watch = data.path!!
|
||||
.replace("/shorts/", "")
|
||||
.replace("/v/", "")
|
||||
.replace("/embed/", "")
|
||||
val bundle = Bundle()
|
||||
bundle.putString("videoId", watch)
|
||||
val frag = PlayerFragment()
|
||||
frag.arguments = bundle
|
||||
supportFragmentManager.beginTransaction()
|
||||
.remove(PlayerFragment())
|
||||
.commit()
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, frag)
|
||||
.commitNow()
|
||||
Handler().postDelayed({
|
||||
val motionLayout = findViewById<MotionLayout>(R.id.playerMotionLayout)
|
||||
motionLayout.transitionToEnd()
|
||||
motionLayout.transitionToStart()
|
||||
}, 100)
|
||||
} else if (data.path!!.contains("/watch") && data.query != null) {
|
||||
Log.d("dafaq", data.query!!)
|
||||
var watch = data.query!!
|
||||
if (watch.contains("&")) {
|
||||
var watches = watch.split("&")
|
||||
for (v in watches) {
|
||||
if (v.contains("v=")) {
|
||||
watch = v
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
var bundle = Bundle()
|
||||
bundle.putString("videoId", watch.replace("v=", ""))
|
||||
var frag = PlayerFragment()
|
||||
frag.arguments = bundle
|
||||
supportFragmentManager.beginTransaction()
|
||||
.remove(PlayerFragment())
|
||||
.commit()
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, frag)
|
||||
.commitNow()
|
||||
Handler().postDelayed({
|
||||
val motionLayout = findViewById<MotionLayout>(R.id.playerMotionLayout)
|
||||
motionLayout.transitionToEnd()
|
||||
motionLayout.transitionToStart()
|
||||
}, 100)
|
||||
} else {
|
||||
var watch = data.path!!.replace("/", "")
|
||||
var bundle = Bundle()
|
||||
bundle.putString("videoId", watch)
|
||||
var frag = PlayerFragment()
|
||||
frag.arguments = bundle
|
||||
supportFragmentManager.beginTransaction()
|
||||
.remove(PlayerFragment())
|
||||
.commit()
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, frag)
|
||||
.commitNow()
|
||||
Handler().postDelayed({
|
||||
val motionLayout = findViewById<MotionLayout>(R.id.playerMotionLayout)
|
||||
motionLayout.transitionToEnd()
|
||||
motionLayout.transitionToStart()
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
|
||||
|
47
app/src/main/java/com/github/libretube/RouterActivity.kt
Normal file
47
app/src/main/java/com/github/libretube/RouterActivity.kt
Normal file
@ -0,0 +1,47 @@
|
||||
package com.github.libretube
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
class RouterActivity : AppCompatActivity() {
|
||||
val TAG = "RouterActivity"
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// Check if Intent Action is ACTION_SEND
|
||||
if (intent?.action == Intent.ACTION_SEND) {
|
||||
if (intent.type == "text/plain" && checkHost(intent)) {
|
||||
// start the main activity using the given URI as data if the host is known
|
||||
handleSendText(intent)
|
||||
} else {
|
||||
// start app as normal if wrong intent type
|
||||
restartMainActivity(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkHost(intent: Intent): Boolean {
|
||||
// check whether the host is known, current solution to replace the broken intent filter
|
||||
val hostsList = resources.getStringArray(R.array.shareHostsList)
|
||||
val intentDataUri: Uri = Uri.parse(intent.getStringExtra(Intent.EXTRA_TEXT))
|
||||
val intentDataHost = intentDataUri.host
|
||||
Log.d(TAG, "$intentDataHost")
|
||||
return hostsList.contains(intentDataHost)
|
||||
}
|
||||
|
||||
private fun handleSendText(intent: Intent) {
|
||||
intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
|
||||
Log.i(TAG, it)
|
||||
val pm: PackageManager = this.packageManager
|
||||
// startIntent(this, MainActivity::class.java doesn't work for the activity aliases needed for the logo switch option
|
||||
val intent = pm.getLaunchIntentForPackage(this.packageName)
|
||||
intent?.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
intent?.data = Uri.parse(it)
|
||||
this.startActivity(intent)
|
||||
this.finishAndRemoveTask()
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,46 @@
|
||||
<item>https://pipedapi.moomoo.me</item>
|
||||
<item>https://pa.mint.lgbt</item>
|
||||
</string-array>
|
||||
<string-array name="shareHostsList">
|
||||
<item>youtube.com"</item>
|
||||
<item>m.youtube.com"</item>
|
||||
<item>www.youtube.com"</item>
|
||||
<item>music.youtube.com"</item>
|
||||
<item>youtu.be"</item>
|
||||
<item>tubus.eduvid.org"</item>
|
||||
<item>invidio.us"</item>
|
||||
<item>dev.invidio.us"</item>
|
||||
<item>www.invidio.us"</item>
|
||||
<item>redirect.invidious.io"</item>
|
||||
<item>invidious.snopyta.org"</item>
|
||||
<item>yewtu.be"</item>
|
||||
<item>tube.connect.cafe"</item>
|
||||
<item>invidious.kavin.rocks"</item>
|
||||
<item>invidious-us.kavin.rocks"</item>
|
||||
<item>invidious.site"</item>
|
||||
<item>vid.mint.lgbt"</item>
|
||||
<item>invidiou.site"</item>
|
||||
<item>invidious.fdn.fr"</item>
|
||||
<item>invidious.048596.xyz"</item>
|
||||
<item>invidious.zee.li"</item>
|
||||
<item>vid.puffyan.us"</item>
|
||||
<item>ytprivate.com"</item>
|
||||
<item>invidious.namazso.eu"</item>
|
||||
<item>invidious.silkky.cloud"</item>
|
||||
<item>invidious.exonip.de"</item>
|
||||
<item>inv.riverside.rocks"</item>
|
||||
<item>invidious.blamefran.net"</item>
|
||||
<item>invidious.moomoo.me"</item>
|
||||
<item>ytb.trom.tf"</item>
|
||||
<item>yt.cyberhost.uk"</item>
|
||||
<item>y.com.cm"</item>
|
||||
<item>piped.tokhmi.xyz"</item>
|
||||
<item>piped.kavin.rocks"</item>
|
||||
<item>piped.silkky.cloud"</item>
|
||||
<item>piped.silkky.cloud"</item>
|
||||
<item>piped.mint.lgbt"</item>
|
||||
<item>il.ax"</item>
|
||||
</string-array>
|
||||
<string-array name="regions">
|
||||
<item>Afghanistan</item>
|
||||
<item>Albania</item>
|
||||
|
Loading…
Reference in New Issue
Block a user