diff --git a/P2Play.iml b/P2Play.iml new file mode 100644 index 0000000..a7938e6 --- /dev/null +++ b/P2Play.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/.DS_Store b/app/.DS_Store new file mode 100644 index 0000000..c5fd63c Binary files /dev/null and b/app/.DS_Store differ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/app.iml b/app/app.iml new file mode 100644 index 0000000..ae00402 --- /dev/null +++ b/app/app.iml @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..0b05edd --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,36 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "org.libre.agosto.p2play" + minSdkVersion 23 + targetSdkVersion 27 + versionCode 1 + versionName "0.1" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support.constraint:constraint-layout:1.1.2' + implementation 'com.android.support:support-v4:27.1.1' + implementation 'com.android.support:design:27.1.1' + implementation 'com.squareup.picasso:picasso:2.71828' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/.DS_Store b/app/src/.DS_Store new file mode 100644 index 0000000..ead2b84 Binary files /dev/null and b/app/src/.DS_Store differ diff --git a/app/src/androidTest/java/org/libre/agosto/p2play/ExampleInstrumentedTest.kt b/app/src/androidTest/java/org/libre/agosto/p2play/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..d86c903 --- /dev/null +++ b/app/src/androidTest/java/org/libre/agosto/p2play/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package org.libre.agosto.p2play + +import android.support.test.InstrumentationRegistry +import android.support.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getTargetContext() + assertEquals("org.libre.agosto.p2play", appContext.packageName) + } +} diff --git a/app/src/main/.DS_Store b/app/src/main/.DS_Store new file mode 100644 index 0000000..5c5539d Binary files /dev/null and b/app/src/main/.DS_Store differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f2dce8f --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/Database.kt b/app/src/main/java/org/libre/agosto/p2play/Database.kt new file mode 100644 index 0000000..d4e9ebd --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/Database.kt @@ -0,0 +1,123 @@ +package org.libre.agosto.p2play + +import android.content.ContentValues +import android.content.Context +import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteException +import android.database.sqlite.SQLiteOpenHelper +import org.libre.agosto.p2play.models.TokenModel +import org.libre.agosto.p2play.models.UserModel + +class Database(context:Context): SQLiteOpenHelper(context,"p2play",null,1) { + val dbName = "p2play" + + private val dbUsers = "CREATE TABLE users(id INTEGER PRIMARY KEY AUTOINCREMENT, uuid INTEGER, username varchar(30), " + + "nsfw INTEGER, email string, followers INTEGER, avatar string, status integer)" + private val dbTokens = "CREATE TABLE tokens(id INTEGER PRIMARY KEY AUTOINCREMENT, token STRING, status INTEGER)" + override fun onCreate(db: SQLiteDatabase?) { + db?.execSQL(dbUsers) + db?.execSQL(dbTokens) + } + + override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) { + db?.execSQL("DROP TABLE users") + db?.execSQL("DROP TABLE tokens") + onCreate(db) + } + + fun newToken(token: TokenModel): Boolean { + val db = writableDatabase + this.closeTokens() + val newToken=ContentValues() + newToken.put("token", token.token) + newToken.put("status", token.status) + + db.insert("tokens",null,newToken) + + return true + } + + fun newUser(user: UserModel): Boolean { + val db = writableDatabase + this.closeUsers() + val newUser=ContentValues() + newUser.put("uuid", user.uuid) + newUser.put("username", user.username) + newUser.put("email", user.email) + newUser.put("nsfw", user.nsfw) + newUser.put("followers", user.followers) + newUser.put("avatar", user.avatar) + newUser.put("status", user.status) + + db.insert("users",null, newUser) + + return true + } + + fun getToken(): TokenModel{ + val db = writableDatabase + var token = TokenModel() + + try { + var cursor= db.rawQuery("SELECT * FROM tokens WHERE status=1 ORDER BY id DESC LIMIT 1",null) + cursor.moveToFirst() + + token.token = cursor.getString(cursor.getColumnIndex("token")).toString() + token.status = cursor.getString(cursor.getColumnIndex("status")).toInt() + + cursor.close() + + return token + + }catch (e:SQLiteException){ + db?.execSQL(dbTokens) + }catch (e:Exception){ + e.printStackTrace() + } + return token + } + + fun getUser(): UserModel{ + val db = writableDatabase + var user = UserModel() + + try { + var cursor= db.rawQuery("SELECT * FROM users WHERE status=1 ORDER BY id DESC LIMIT 1",null) + cursor.moveToFirst() + + user.uuid = cursor.getString(cursor.getColumnIndex("uuid")).toInt() + user.username = cursor.getString(cursor.getColumnIndex("username")).toString() + user.email = cursor.getString(cursor.getColumnIndex("email")).toString() + user.nsfw = cursor.getString(cursor.getColumnIndex("nsfw")).toBoolean() + user.followers = cursor.getString(cursor.getColumnIndex("followers")).toInt() + user.avatar = cursor.getString(cursor.getColumnIndex("avatar")).toString() + user.status = cursor.getString(cursor.getColumnIndex("status")).toInt() + + cursor.close() + + return user + + }catch (e:SQLiteException){ + db?.execSQL(dbTokens) + }catch (e:Exception){ + e.printStackTrace() + } + return user + } + + private fun closeTokens(){ + val db = writableDatabase + db.execSQL("UPDATE tokens SET status=-1 WHERE 1") + } + + private fun closeUsers(){ + val db = writableDatabase + db.execSQL("UPDATE users SET status=-1 WHERE 1") + } + + fun logout(){ + closeUsers() + closeTokens() + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/HostActivity.kt b/app/src/main/java/org/libre/agosto/p2play/HostActivity.kt new file mode 100644 index 0000000..6991b29 --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/HostActivity.kt @@ -0,0 +1,89 @@ +package org.libre.agosto.p2play + +import android.content.Intent +import android.content.SharedPreferences +import android.os.AsyncTask +import android.support.v7.app.AppCompatActivity +import android.os.Bundle +import android.os.Looper +import android.preference.PreferenceManager +import android.util.Log +import kotlinx.android.synthetic.main.activity_host.* +import org.libre.agosto.p2play.ajax.Client + +class HostActivity : AppCompatActivity() { + lateinit var settings: SharedPreferences + lateinit var editor: SharedPreferences.Editor + val client:Client = Client() + val _db = Database(this) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_host) + settings = this.getSharedPreferences("P2play",0) + editor = settings.edit() + ManagerSingleton.context = this + button.setOnClickListener { getKeys() } + + val host = settings.getString("hostP2play","") + if(host!=""){ + ManagerSingleton.url=host + checkUser() + startApp() + this.finish() + } + } + + fun checkUser(){ + val token = _db.getToken() + val user = _db.getUser() + if(token.status == 1 && user.status==1){ + ManagerSingleton.user = user + ManagerSingleton.token = token + } + else{ + _db.logout() + } + } + + fun saveHost(){ + val host = hostText.text.toString() + editor.putString("hostP2play",host) + editor.apply() + startApp() + } + + fun getKeys(){ + button.isEnabled = false + var host = hostText.text.toString() + host = host.replace("http://","") + host = host.replace("https://","") + host = host.replace("/","") + ManagerSingleton.url = host + AsyncTask.execute { + Looper.prepare() + val keys = client.getKeys() + if(keys.client_id!=""){ + editor.putString("client_id",keys.client_id) + editor.putString("client_secret",keys.client_secret) + editor.apply() + saveHost() + } + else{ + + runOnUiThread { + ManagerSingleton.Toast(getString(R.string.errorMsg)) + button.isEnabled = true + } + } + } + } + + fun startApp(){ + runOnUiThread { + ManagerSingleton.Toast(getString(R.string.finallyMsg)) + val intent = Intent(ManagerSingleton.context,MainActivity::class.java) + startActivity(intent) + } + } +} diff --git a/app/src/main/java/org/libre/agosto/p2play/LoginActivity.kt b/app/src/main/java/org/libre/agosto/p2play/LoginActivity.kt new file mode 100644 index 0000000..99e9096 --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/LoginActivity.kt @@ -0,0 +1,86 @@ +package org.libre.agosto.p2play + +import android.content.Intent +import android.content.SharedPreferences +import android.os.AsyncTask +import android.support.v7.app.AppCompatActivity +import android.os.Bundle +import android.os.Looper +import android.util.Log +import kotlinx.android.synthetic.main.activity_login.* +import org.libre.agosto.p2play.ajax.Auth + +class LoginActivity : AppCompatActivity() { + private val _auth = Auth() + lateinit var settings: SharedPreferences + lateinit var client_id: String + lateinit var client_secret: String + private lateinit var _db: Database + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_login) + setTitle(R.string.action_login) + ManagerSingleton.context = this + _db = Database(this) + + settings = this.getSharedPreferences("P2play",0) + client_id = settings.getString("client_id", "") + client_secret = settings.getString("client_secret", "") + + registerActionBtn.setOnClickListener { startActivity(Intent(this, RegisterActivity::class.java)) } + loginBtn.setOnClickListener { tryLogin() } + } + + fun tryLogin(){ + loginBtn.isEnabled = false; + val username = userText.text.toString() + val password = passwordText.text.toString() + + AsyncTask.execute { + Looper.prepare() + val token = _auth.login(username, password, client_id, client_secret) + + Log.d("token", token.token ) + Log.d("status", token.status.toString() ) + + + when(token.status.toString()){ + "1" -> { + _db.newToken(token) + ManagerSingleton.token = token + getUser() + } + "0" -> { + runOnUiThread { + ManagerSingleton.Toast(getString(R.string.loginError_msg)) + } + } + "-1" -> { + runOnUiThread { + loginBtn.isEnabled = true + ManagerSingleton.Toast(getString(R.string.loginFailed_msg)) + } + } + } + + } + } + + fun getUser(){ + val user = _auth.me(ManagerSingleton.token.token) + if(user.status == 1){ + _db.newUser(user) + ManagerSingleton.user = user + runOnUiThread { + ManagerSingleton.Toast(getString(R.string.loginSuccess_msg)) + finish() + } + } + else{ + runOnUiThread { + ManagerSingleton.Toast(getString(R.string.loginError_msg)) + } + } + } +} diff --git a/app/src/main/java/org/libre/agosto/p2play/MainActivity.kt b/app/src/main/java/org/libre/agosto/p2play/MainActivity.kt new file mode 100644 index 0000000..3350ce7 --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/MainActivity.kt @@ -0,0 +1,226 @@ +package org.libre.agosto.p2play + +import android.content.Intent +import android.os.AsyncTask +import android.os.Bundle +import android.support.design.widget.Snackbar +import android.support.design.widget.NavigationView +import android.support.v4.view.GravityCompat +import android.support.v7.app.ActionBarDrawerToggle +import android.support.v7.app.AppCompatActivity +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.widget.ImageView +import com.squareup.picasso.Picasso +import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.app_bar_main.* +import kotlinx.android.synthetic.main.nav_header_main.* +import org.libre.agosto.p2play.adapters.VideosAdapter +import org.libre.agosto.p2play.ajax.Videos +import org.libre.agosto.p2play.models.VideoModel + +class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener { + private lateinit var recyclerView: RecyclerView + private lateinit var viewAdapter: RecyclerView.Adapter<*> + private lateinit var viewManager: RecyclerView.LayoutManager + val client: Videos = Videos() + private lateinit var lastItem: MenuItem + lateinit var myMenu: Menu + val _db = Database(this) + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + setSupportActionBar(toolbar) + + /* fab.setOnClickListener { view -> + Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) + .setAction("Action", null).show() + } */ + + val toggle = ActionBarDrawerToggle( + this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) + drawer_layout.addDrawerListener(toggle) + toggle.syncState() + + ManagerSingleton.context = this + + nav_view.setNavigationItemSelectedListener(this) + viewManager = LinearLayoutManager(this) + + // val data = arrayOf("test","test2","test3","test4") + // viewAdapter = VideosAdapter(data) + + this.setData(arrayListOf()) + + this.getLastVideos() + } + + fun setData(data:ArrayList){ + viewAdapter = VideosAdapter(data) + + recyclerView = findViewById(R.id.list).apply { + // use this setting to improve performance if you know that changes + // in content do not change the layout size of the RecyclerView + setHasFixedSize(true) + + // use a linear layout manager + layoutManager = viewManager + + // specify an viewAdapter (see also next example) + adapter = viewAdapter + + } + + } + + fun getLastVideos(){ + setTitle(R.string.title_recent) + AsyncTask.execute { + val videos = client.getLastVideos() + runOnUiThread { + this.setData(videos) + } + } + } + + fun getPopularVideos(){ + setTitle(R.string.title_popular) + AsyncTask.execute { + val videos = client.getPopularVideos() + runOnUiThread { + this.setData(videos) + } + } + } + + fun getLocalVideos(){ + setTitle(R.string.title_local) + AsyncTask.execute { + val videos = client.getLocalVideos() + runOnUiThread { + this.setData(videos) + } + } + } + + fun getMyVideos(){ + setTitle(R.string.title_myVideos) + AsyncTask.execute { + val videos = client.myVideos(ManagerSingleton.token.token) + runOnUiThread { + this.setData(videos) + } + } + } + + override fun onBackPressed() { + if (drawer_layout.isDrawerOpen(GravityCompat.START)) { + drawer_layout.closeDrawer(GravityCompat.START) + } else { + super.onBackPressed() + } + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + // Inflate the menu; this adds items to the action bar if it is present. + menuInflater.inflate(R.menu.main, menu) + myMenu = menu + setSideData() + return true + } + + override fun onPrepareOptionsMenu(menu: Menu?): Boolean { + myMenu = menu!! + + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + when (item.itemId) { + R.id.action_settings -> return true + R.id.action_login -> { + val intent = Intent(this, LoginActivity::class.java) + startActivity(intent) + return true + } + R.id.action_logout -> { + logout() + return true + } + else -> return super.onOptionsItemSelected(item) + } + } + + override fun onNavigationItemSelected(item: MenuItem): Boolean { + // Handle navigation view item clicks here. + + // if(::lastItem.isInitialized){ + // lastItem.isChecked = false + // } + lastItem = item + // item.isChecked = true + when (item.itemId) { + R.id.nav_popular-> { + getPopularVideos() + } + R.id.nav_recent-> { + getLastVideos() + } + R.id.nav_local-> { + getLocalVideos() + } + } + + drawer_layout.closeDrawer(GravityCompat.START) + return true + } + + override fun onResume() { + super.onResume() + ManagerSingleton.context = this + setSideData() + } + + private fun setSideData(){ + if(ManagerSingleton.user.status == 1){ + side_usernameTxt?.text = ManagerSingleton.user.username + side_emailTxt?.text = ManagerSingleton.user.email + if(ManagerSingleton.user.avatar!="" && side_imageView != null) + Picasso.get().load("https://"+ManagerSingleton.url+ManagerSingleton.user.avatar).into(side_imageView) + side_imageView?.setOnClickListener { + getMyVideos() + drawer_layout.closeDrawer(GravityCompat.START) + } + if(::myMenu.isInitialized){ + myMenu.findItem(R.id.action_login).isVisible = false + myMenu.findItem(R.id.action_logout).isVisible = true + } + } + } + + fun logout(){ + if(::myMenu.isInitialized){ + myMenu.findItem(R.id.action_login).isVisible = true + myMenu.findItem(R.id.action_logout).isVisible = false + } + side_usernameTxt?.text = getString(R.string.nav_header_title) + side_emailTxt?.text = getString(R.string.nav_header_subtitle) + side_imageView?.setImageResource(R.mipmap.ic_launcher_round) + side_imageView?.setOnClickListener { } + _db.logout() + ManagerSingleton.logout() + + ManagerSingleton.Toast(getString(R.string.logout_msg)) + + } + + +} diff --git a/app/src/main/java/org/libre/agosto/p2play/ManagerSingleton.kt b/app/src/main/java/org/libre/agosto/p2play/ManagerSingleton.kt new file mode 100644 index 0000000..65b9e60 --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/ManagerSingleton.kt @@ -0,0 +1,23 @@ +package org.libre.agosto.p2play + +import android.content.Context +import org.libre.agosto.p2play.models.TokenModel +import org.libre.agosto.p2play.models.UserModel + +object ManagerSingleton { + var context: Context?= null + var url: String?= null + var user: UserModel = UserModel() + var token: TokenModel = TokenModel() + // var keys: + + fun Toast(text: String?) { + if(this.context == null) { return } + android.widget.Toast.makeText(this.context, text, android.widget.Toast.LENGTH_SHORT).show() + } + + fun logout(){ + user = UserModel() + token = TokenModel() + } +} \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/RegisterActivity.kt b/app/src/main/java/org/libre/agosto/p2play/RegisterActivity.kt new file mode 100644 index 0000000..a59b630 --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/RegisterActivity.kt @@ -0,0 +1,12 @@ +package org.libre.agosto.p2play + +import android.support.v7.app.AppCompatActivity +import android.os.Bundle + +class RegisterActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_register) + } +} diff --git a/app/src/main/java/org/libre/agosto/p2play/ReproductorActivity.kt b/app/src/main/java/org/libre/agosto/p2play/ReproductorActivity.kt new file mode 100644 index 0000000..d24265d --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/ReproductorActivity.kt @@ -0,0 +1,39 @@ +package org.libre.agosto.p2play + +import android.support.v7.app.AppCompatActivity +import android.os.Bundle +import android.util.Log +import com.squareup.picasso.Picasso +import kotlinx.android.synthetic.main.activity_reproductor.* +import org.libre.agosto.p2play.models.VideoModel + +class ReproductorActivity : AppCompatActivity() { + lateinit var video:VideoModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_reproductor) + ManagerSingleton.context = this + + videoView.settings.javaScriptEnabled = true + videoView.settings.allowContentAccess = true + try { + this.video = this.intent.extras.getSerializable("video") as VideoModel + tittleVideoTxt.text = this.video.name + viewsTxt.text = this.video.views.toString() + getString(R.string.view_text) + userTxt.text = this.video.username + descriptionVideoTxt.text = this.video.description + + if(this.video.userImageUrl!="") + Picasso.get().load("https://"+ManagerSingleton.url+this.video.userImageUrl).into(userImg) + videoView.loadUrl("https://"+ManagerSingleton.url+this.video.embedUrl) + Log.d("url", videoView.url) + } + catch (err:Exception){ + err.printStackTrace() + Log.d("Error", err?.message) + } + + subscribeBtn.setOnClickListener { ManagerSingleton.Toast(getString(R.string.comming)) } + } +} diff --git a/app/src/main/java/org/libre/agosto/p2play/adapters/VideosAdapter.kt b/app/src/main/java/org/libre/agosto/p2play/adapters/VideosAdapter.kt new file mode 100644 index 0000000..a5bae25 --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/adapters/VideosAdapter.kt @@ -0,0 +1,79 @@ +package org.libre.agosto.p2play.adapters + +import android.app.Activity +import android.content.Intent +import android.graphics.drawable.Drawable +import android.os.AsyncTask +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import com.squareup.picasso.Picasso +import org.libre.agosto.p2play.MainActivity +import org.libre.agosto.p2play.ManagerSingleton +import org.libre.agosto.p2play.R +import org.libre.agosto.p2play.ReproductorActivity +import org.libre.agosto.p2play.models.VideoModel +import java.io.InputStream +import java.io.Serializable +import java.net.URL + +class VideosAdapter(private val myDataset: ArrayList) : + RecyclerView.Adapter() { + + // Provide a reference to the views for each data item + // Complex data items may need more than one view per item, and + // you provide access to all the views for a data item in a view holder. + // Each data item is just a string in this case that is shown in a TextView. + class ViewHolder(val view: View) : RecyclerView.ViewHolder(view){ + val thumb: ImageView + val userImg: ImageView + val tittle: TextView + val description: TextView + + init { + // Define click listener for the ViewHolder's View + tittle = view.findViewById(R.id.tittleTxt) + description = view.findViewById(R.id.descriptionTxt) + thumb = view.findViewById(R.id.thumb) + userImg = view.findViewById(R.id.userImg) + } + } + + + // Create new views (invoked by the layout manager) + override fun onCreateViewHolder(parent: ViewGroup, + viewType: Int): VideosAdapter.ViewHolder { + // create a new view + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.view_video, parent, false) as View + // set the view's size, margins, paddings and layout parameters + return ViewHolder(view) + } + + // Replace the contents of a view (invoked by the layout manager) + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + // - get element from your dataset at this position + // - replace the contents of the view with that element + holder.tittle.text = myDataset[position].name + Picasso.get().load("https://"+ManagerSingleton.url+myDataset[position].thumbUrl).into(holder.thumb) + holder.thumb.setOnClickListener { + val intent = Intent(ManagerSingleton.context, ReproductorActivity::class.java) + intent.putExtra("video", myDataset[position] as Serializable) + ManagerSingleton.context!!.startActivity(intent) + } + if(myDataset[position].userImageUrl!="") + Picasso.get().load("https://"+ManagerSingleton.url+myDataset[position].userImageUrl).into(holder.userImg); + + val viewsText = ManagerSingleton.context!!.getString(R.string.view_text) + val timeText = ManagerSingleton.context!!.getString(R.string.time_text) + holder.description.text = myDataset[position].username+" - "+myDataset[position].views+" "+viewsText+" - "+myDataset[position].duration+" "+timeText + + } + + // Return the size of your dataset (invoked by the layout manager) + override fun getItemCount() = myDataset.size +} \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/ajax/Auth.kt b/app/src/main/java/org/libre/agosto/p2play/ajax/Auth.kt new file mode 100644 index 0000000..c683052 --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/ajax/Auth.kt @@ -0,0 +1,112 @@ +package org.libre.agosto.p2play.ajax + +import android.support.design.widget.Snackbar +import android.util.JsonReader +import android.util.Log +import org.libre.agosto.p2play.ManagerSingleton +import org.libre.agosto.p2play.models.TokenModel +import org.libre.agosto.p2play.models.UserModel +import java.io.InputStreamReader + +class Auth: Client() { + val stockParams = "grant_type=password" + + fun login(username: String, password: String, client_id: String, client_secret: String): TokenModel{ + var con = this._newCon("users/token","POST") + val params:String= "$stockParams&username=$username&password=$password&client_id=$client_id&client_secret=$client_secret" + con.outputStream.write(params.toByteArray()) + var token = TokenModel() + + try { + + if(con.responseCode==200){ + var response = InputStreamReader(con.inputStream) + var data = JsonReader(response) + data.beginObject() + + while(data.hasNext()){ + val k = data.nextName() + when(k.toString()){ + "access_token" -> token.token = "Bearer " + data.nextString() + else -> data.skipValue() + } + } + + data.endObject() + token.status = 1 + + } + else{ + Log.d("Status", con.responseMessage) + } + } + catch (err: Exception){ + err.printStackTrace() + token.status = 0 + } + + return token + } + + fun me(token: String): UserModel{ + var con = this._newCon("users/me","GET", token) + + var user = UserModel() + + try { + + if(con.responseCode==200){ + var response = InputStreamReader(con.inputStream) + var data = JsonReader(response) + data.beginObject() + + while(data.hasNext()){ + val k = data.nextName() + when(k.toString()){ + "id" -> user.uuid = data.nextInt() + "username" -> user.username = data.nextString() + "email" -> user.email = data.nextString() + "displayNSFW" -> user.nsfw = data.nextBoolean() + "account" -> { + data.beginObject() + while (data.hasNext()){ + val l = data.nextName() + when(l.toString()){ + "followersCount" -> user.followers = data.nextInt() + "avatar" -> { + data.beginObject() + while (data.hasNext()){ + val m = data.nextName() + when (m.toString()){ + "path" -> user.avatar = data.nextString() + else -> data.skipValue() + } + } + data.endObject() + } + else -> data.skipValue() + } + } + data.endObject() + } + else -> data.skipValue() + } + } + + data.endObject() + user.status = 1 + + } + else{ + Log.d("Status", con.responseMessage) + } + } + catch (err: Exception){ + err.printStackTrace() + user.status = 0 + } + + return user + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/ajax/Client.kt b/app/src/main/java/org/libre/agosto/p2play/ajax/Client.kt new file mode 100644 index 0000000..815b059 --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/ajax/Client.kt @@ -0,0 +1,69 @@ +package org.libre.agosto.p2play.ajax + +import android.content.SharedPreferences +import android.util.JsonReader +import android.util.Log +import org.libre.agosto.p2play.ManagerSingleton +import org.libre.agosto.p2play.models.HostModel +import java.io.InputStreamReader +import java.net.HttpURLConnection +import java.net.URL + +open class Client { + + + protected fun _newCon(uri: String, method: String, token: String = ""): HttpURLConnection { + var url = URL("https://"+ManagerSingleton.url+"/api/v1/"+uri) + var con = url.openConnection() as HttpURLConnection + + con.setRequestProperty("User-Agent", "P2play/0.0.1") + con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded") + con.setRequestProperty("Accept", "*/*") + + if(token != ""){ + con.setRequestProperty("Authorization", token) + } + + con.requestMethod=method + con.connectTimeout=10000 + con.readTimeout=10000 + + if(method.equals("POST")) + con.doOutput=true + + return con + } + + fun getKeys():HostModel{ + var con=this._newCon("oauth-clients/local","GET") + var keys = HostModel("","") + try { + if (con.responseCode == 200) { + var response = InputStreamReader(con.inputStream) + var data = JsonReader(response) + data.beginObject() + while (data.hasNext()) { + val key = data.nextName() + when (key.toString()) { + "client_id"->{ + keys.client_id = data.nextString() + } + "client_secret"->{ + keys.client_secret = data.nextString() + } + else->{ + data.skipValue() + } + } + } + } + Log.d("Key",keys.client_id) + return keys + } catch(err:Exception){ + Log.d("Error",err.message) + return keys + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt b/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt new file mode 100644 index 0000000..4f1865d --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/ajax/Videos.kt @@ -0,0 +1,136 @@ +package org.libre.agosto.p2play.ajax + +import android.util.JsonReader +import android.util.JsonToken +import android.util.Log +import org.libre.agosto.p2play.models.VideoModel +import java.io.InputStreamReader + +class Videos: Client() { + + fun parseVideos(data: JsonReader): ArrayList{ + var videos = arrayListOf() + data.beginObject() + while (data.hasNext()){ + when(data.nextName()){ + "data"->{ + data.beginArray() + while (data.hasNext()) { + val video = VideoModel() + data.beginObject() + while (data.hasNext()){ + val key = data.nextName() + when (key.toString()) { + "name"->{ + video.name= data.nextString() + } + "description"->{ + if(data.peek() == JsonToken.STRING) + video.description = data.nextString() + else + data.skipValue() + } + "duration"->{ + video.duration = data.nextInt() + } + "thumbnailPath"->{ + video.thumbUrl = data.nextString() + } + "embedPath"->{ + video.embedUrl = data.nextString() + } + "views"->{ + video.views = data.nextInt() + } + "account"->{ + data.beginObject() + while (data.hasNext()){ + val acKey = data.nextName() + when(acKey.toString()){ + "name"->video.username=data.nextString() + "avatar"->{ + if(data.peek() == JsonToken.BEGIN_OBJECT){ + data.beginObject() + while (data.hasNext()){ + val avKey = data.nextName() + when(avKey){ + "path"-> video.userImageUrl = data.nextString() + else-> data.skipValue() + } + } + data.endObject() + } + else + data.skipValue() + + } + else-> data.skipValue() + } + } + data.endObject() + } + else->{ + data.skipValue() + } + } + } + data.endObject() + videos.add(video) + } + data.endArray() + } + else-> data.skipValue() + } + } + data.endObject() + + return videos + } + + private fun getVideos(page:Int = 0, sort:String = "-publishedAt", filter:String = ""):ArrayList{ + val params = "start=$page&sort=$sort&filter=$filter" + var con=this._newCon("videos?$params","GET") + var videos = arrayListOf() + try { + if (con.responseCode == 200) { + var response = InputStreamReader(con.inputStream) + var data = JsonReader(response) + videos = parseVideos(data) + } + } catch(err:Exception){ + err?.printStackTrace() + Log.d("TypeErr",err?.message ,err.cause) + Log.d("Error","fallo la coneccion") + } + return videos + } + + fun getLastVideos(): ArrayList{ + return this.getVideos() + } + + fun getPopularVideos(): ArrayList{ + return this.getVideos(0,"-views") + } + + fun getLocalVideos(): ArrayList{ + return this.getVideos(0,"-publishedAt", "local") + } + + fun myVideos(token: String): ArrayList{ + var con=this._newCon("users/me/videos","GET", token) + var videos = arrayListOf() + try { + if (con.responseCode == 200) { + var response = InputStreamReader(con.inputStream) + var data = JsonReader(response) + videos = parseVideos(data) + } + } catch(err:Exception){ + err?.printStackTrace() + Log.d("TypeErr",err?.message ,err.cause) + Log.d("Error","fallo la coneccion") + } + return videos + } +} \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/models/HostModel.kt b/app/src/main/java/org/libre/agosto/p2play/models/HostModel.kt new file mode 100644 index 0000000..34dbe7f --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/models/HostModel.kt @@ -0,0 +1,3 @@ +package org.libre.agosto.p2play.models + +class HostModel (var client_id:String, var client_secret:String) \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/models/TokenModel.kt b/app/src/main/java/org/libre/agosto/p2play/models/TokenModel.kt new file mode 100644 index 0000000..dfe5dbc --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/models/TokenModel.kt @@ -0,0 +1,6 @@ +package org.libre.agosto.p2play.models + +class TokenModel ( + var token: String = "", + var status: Int = -1 +) \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/models/UserModel.kt b/app/src/main/java/org/libre/agosto/p2play/models/UserModel.kt new file mode 100644 index 0000000..fee5715 --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/models/UserModel.kt @@ -0,0 +1,12 @@ +package org.libre.agosto.p2play.models + +class UserModel ( + var id: Int = 0, + var uuid: Int = 0, + var username: String = "", + var email: String = "", + var nsfw: Boolean = true, + var followers: Int = 0, + var avatar: String = "", + var status: Int = -1 +) \ No newline at end of file diff --git a/app/src/main/java/org/libre/agosto/p2play/models/VideoModel.kt b/app/src/main/java/org/libre/agosto/p2play/models/VideoModel.kt new file mode 100644 index 0000000..0513e56 --- /dev/null +++ b/app/src/main/java/org/libre/agosto/p2play/models/VideoModel.kt @@ -0,0 +1,14 @@ +package org.libre.agosto.p2play.models + +import java.io.Serializable + +class VideoModel( + var name:String="", + var description:String="", + var thumbUrl:String="", + var userImageUrl:String="", + var embedUrl:String="", + var duration:Number=0, + var username:String="", + var views:Number=0 + ):Serializable \ No newline at end of file diff --git a/app/src/main/res/.DS_Store b/app/src/main/res/.DS_Store new file mode 100644 index 0000000..46d685e Binary files /dev/null and b/app/src/main/res/.DS_Store differ diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/.DS_Store b/app/src/main/res/drawable/.DS_Store new file mode 100644 index 0000000..858eb4a Binary files /dev/null and b/app/src/main/res/drawable/.DS_Store differ diff --git a/app/src/main/res/drawable/default_avatar.png b/app/src/main/res/drawable/default_avatar.png new file mode 100644 index 0000000..4b7fd2c Binary files /dev/null and b/app/src/main/res/drawable/default_avatar.png differ diff --git a/app/src/main/res/drawable/ic_add_circle_black_24dp.xml b/app/src/main/res/drawable/ic_add_circle_black_24dp.xml new file mode 100644 index 0000000..db4e035 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_circle_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_black_24dp.xml b/app/src/main/res/drawable/ic_home_black_24dp.xml new file mode 100644 index 0000000..70fb291 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_menu_camera.xml b/app/src/main/res/drawable/ic_menu_camera.xml new file mode 100644 index 0000000..0d9ea10 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_camera.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_menu_gallery.xml b/app/src/main/res/drawable/ic_menu_gallery.xml new file mode 100644 index 0000000..f6872c4 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_gallery.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu_manage.xml b/app/src/main/res/drawable/ic_menu_manage.xml new file mode 100644 index 0000000..c1be60b --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_manage.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_menu_send.xml b/app/src/main/res/drawable/ic_menu_send.xml new file mode 100644 index 0000000..00c668c --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_send.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu_share.xml b/app/src/main/res/drawable/ic_menu_share.xml new file mode 100644 index 0000000..a28fb9e --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_share.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu_slideshow.xml b/app/src/main/res/drawable/ic_menu_slideshow.xml new file mode 100644 index 0000000..209aa64 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_slideshow.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/icon.png b/app/src/main/res/drawable/icon.png new file mode 100644 index 0000000..7354a5f Binary files /dev/null and b/app/src/main/res/drawable/icon.png differ diff --git a/app/src/main/res/drawable/side_nav_bar.xml b/app/src/main/res/drawable/side_nav_bar.xml new file mode 100644 index 0000000..6d81870 --- /dev/null +++ b/app/src/main/res/drawable/side_nav_bar.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_host.xml b/app/src/main/res/layout/activity_host.xml new file mode 100644 index 0000000..2049a50 --- /dev/null +++ b/app/src/main/res/layout/activity_host.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + +