diff --git a/app/src/main/java/com/github/opfromthestart/openfunny/MainActivity.kt b/app/src/main/java/com/github/opfromthestart/openfunny/MainActivity.kt index e1f2898..5776ac1 100644 --- a/app/src/main/java/com/github/opfromthestart/openfunny/MainActivity.kt +++ b/app/src/main/java/com/github/opfromthestart/openfunny/MainActivity.kt @@ -1,5 +1,6 @@ package com.github.opfromthestart.openfunny +import android.annotation.SuppressLint import android.app.Activity import android.graphics.Bitmap import android.graphics.BitmapFactory @@ -9,12 +10,18 @@ import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.annotation.FloatRange import androidx.compose.animation.core.tween import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.offset import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.MaterialTheme @@ -32,11 +39,14 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalView import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp import androidx.core.view.WindowCompat import com.github.opfromthestart.openfunny.ui.theme.Purple40 import com.github.opfromthestart.openfunny.ui.theme.Purple80 @@ -127,25 +137,26 @@ fun OpenFunnyMain() { } if (start) { OpenFunnyTheme { - // A surface container using the 'background' color from the theme Surface( modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colors.background ) { Text(text = "iFunny is loading") } } } else { - // A surface container using the 'background' color from the theme + OpenFunnyTheme() { + Surface( modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colors.background ) { ImageCarousel() } } + } } +val sizePx: Float = MainActivity.bounds.right.toFloat() + @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterialApi::class) @Composable fun ImageCarousel() { @@ -161,129 +172,131 @@ fun ImageCarousel() { var curImg_n: ImageBitmap? by remember { mutableStateOf(null) } + var comments: Array by remember { + mutableStateOf(Array(0) { "" }) + } val imgs = 1000 + // println(sizePx) - val sizePx: Float = MainActivity.bounds.right.toFloat() - println(sizePx) - - Log.i(null, "Test ${curInd.currentValue}") +// Log.i(null, "Test ${curInd.currentValue}") if (curInd.currentValue in 0 until imgs) { LaunchedEffect(curInd.currentValue) { GlobalScope.async { Scraper.getImage(curInd.currentValue) { Log.i("OpenFunny", "cur img gotten") var b = BitmapFactory.decodeByteArray(it, 0, it.size) - b = Bitmap.createBitmap(b, 0, 0, b.width, b.height-20) + b = Bitmap.createBitmap(b, 0, 0, b.width, b.height - 20) val ib = b?.asImageBitmap() - if (curInd.currentValue%3 == 0) { + if (curInd.currentValue % 3 == 0) { curImg = ib - } - else if (curInd.currentValue%3 == 1) { + } else if (curInd.currentValue % 3 == 1) { curImg_n = ib - } - else if (curInd.currentValue%3 == 2) { + } else if (curInd.currentValue % 3 == 2) { curImg_p = ib } } - Scraper.getImage(curInd.currentValue+1) { + Scraper.getImage(curInd.currentValue + 1) { Log.i("OpenFunny", "cur imgn gotten") var b = BitmapFactory.decodeByteArray(it, 0, it.size) - b = Bitmap.createBitmap(b, 0, 0, b.width, b.height-20) + b = Bitmap.createBitmap(b, 0, 0, b.width, b.height - 20) val ib = b?.asImageBitmap() - if (curInd.currentValue%3 == 2) { + if (curInd.currentValue % 3 == 2) { curImg = ib - } - else if (curInd.currentValue%3 == 0) { + } else if (curInd.currentValue % 3 == 0) { curImg_n = ib - } - else if (curInd.currentValue%3 == 1) { + } else if (curInd.currentValue % 3 == 1) { curImg_p = ib } } - Scraper.getImage(curInd.currentValue-1) { + Scraper.getImage(curInd.currentValue - 1) { Log.i("OpenFunny", "cur imgp gotten") var b = BitmapFactory.decodeByteArray(it, 0, it.size) - b = Bitmap.createBitmap(b, 0, 0, b.width, b.height-20) + b = Bitmap.createBitmap(b, 0, 0, b.width, b.height - 20) val ib = b?.asImageBitmap() - if (curInd.currentValue%3 == 1) { + if (curInd.currentValue % 3 == 1) { curImg = ib - } - else if (curInd.currentValue%3 == 2) { + } else if (curInd.currentValue % 3 == 2) { curImg_n = ib - } - else if (curInd.currentValue%3 == 0) { + } else if (curInd.currentValue % 3 == 0) { curImg_p = ib } } + Scraper.getComments(curInd.currentValue) { + Log.i("OpenFunny", "comments gotten") + comments = it + } } } } - val posMap = (0 until imgs).map { -it *sizePx to it }.toMap() + val posMap = (0 until imgs).associateBy { -it * sizePx } - if (curImg != null) { - if (curImg_p != null && curImg_n != null) { - Image( - bitmap = curImg_p!!, - contentDescription = "thing", - modifier = Modifier - .swipeable( - curInd, - posMap, - Orientation.Horizontal - ) - .offset { - IntOffset( - ((curInd.offset.value - 2*sizePx) % (3 * sizePx) + sizePx ).toInt(), - 0 - ) - }) - Image( - bitmap = curImg!!, - contentDescription = "thing", - modifier = Modifier - .swipeable( - curInd, - posMap, - Orientation.Horizontal - ) - .offset { - IntOffset( - ((curInd.offset.value - sizePx) % (3 * sizePx) + sizePx).toInt(), - 0 - ) - }) - Image( - bitmap = curImg_n!!, - contentDescription = "thing", - modifier = Modifier - .swipeable( - curInd, - posMap, - Orientation.Horizontal - ) - .offset { IntOffset(((curInd.offset.value ) % (3 * sizePx)+ sizePx).toInt(), 0) }) + val comment = remember { + SwipeableState(false, tween()) + } + val cmap = mapOf(0f to false, -1000f to true) + Box(modifier = Modifier + .swipeable( + curInd, + posMap, + Orientation.Horizontal + ) + .swipeable(comment, cmap, Orientation.Vertical)) + IFunnyImage( + bitmap = curImg_p, + pos = ((curInd.offset.value - 2 * sizePx) % (3 * sizePx) + sizePx).toInt(), + map = posMap, + swipe = curInd + ) + IFunnyImage( + bitmap = curImg, + pos = ((curInd.offset.value - sizePx) % (3 * sizePx) + sizePx).toInt(), + map = posMap, + swipe = curInd + ) + IFunnyImage( + bitmap = curImg_n, + pos = ((curInd.offset.value) % (3 * sizePx) + sizePx).toInt(), + map = posMap, + swipe = curInd + ) + var mod =Modifier + .background(MaterialTheme.colors.background) + .fillMaxWidth() + Column(modifier = Modifier.offset { + IntOffset( + ((curInd.offset.value) % (sizePx)).toInt(), + 2000 + comment.offset.value.toInt() + ) + } + ) { + for (i in comments) { + Text( + i, + modifier = mod + ) + } + } +} - } else { - val ibv = curImg ?: curImg_n // This guarantees it is not null +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun IFunnyImage( + bitmap: ImageBitmap?, + pos: Int, + swipe: SwipeableState, + map: Map +) { + if (bitmap != null) { Image( - bitmap = ibv!!, + bitmap = bitmap, contentDescription = "thing", modifier = Modifier - .swipeable( - curInd, - posMap, - Orientation.Horizontal - ) - .offset { - IntOffset( - ((curInd.offset.value ) % sizePx).toInt(), - 0 - ) - }) - } + .offset { IntOffset(pos, 0) } + .fillMaxWidth()) } else { - Text(text = "Image loading") + Text(text = "Image loading",modifier = Modifier + .offset { IntOffset(pos, 0) }) } } \ No newline at end of file diff --git a/app/src/main/java/com/github/opfromthestart/openfunny/Scraper.kt b/app/src/main/java/com/github/opfromthestart/openfunny/Scraper.kt index c0e2f0f..494abac 100644 --- a/app/src/main/java/com/github/opfromthestart/openfunny/Scraper.kt +++ b/app/src/main/java/com/github/opfromthestart/openfunny/Scraper.kt @@ -36,4 +36,6 @@ object Scraper { external fun getImage(i: Int, callback: Function) + + external fun getComments(i: Int, callback: Function, Unit>) } \ No newline at end of file diff --git a/rust/src/lib.rs b/rust/src/lib.rs index aa8d12e..7bfafe3 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -19,6 +19,7 @@ struct IFunnyImage { smiles: usize, title: String, url: String, + id: String, } #[derive(Deserialize, Default, Debug)] @@ -27,10 +28,26 @@ struct IFunnyImages { page_count: usize, items: Vec, } +#[derive(Deserialize, Default, Debug)] +struct User { + nick: String, +} +#[derive(Deserialize, Default, Debug)] +struct Comment { + text: String, + user: User, +} + +#[derive(Deserialize, Default, Debug)] +struct Comments { + items: Vec, +} static IMAGES: Lazy> = Lazy::new(|| Mutex::new(IFunnyImages::default())); static IMAGEBUFFERS: Lazy>>> = Lazy::new(|| Mutex::new(HashMap::new())); +static COMMENTBUFFERS: Lazy>>> = + Lazy::new(|| Mutex::new(HashMap::new())); static HEADER: Lazy = Lazy::new(|| { let mut h = HeaderMap::new(); h.insert( @@ -87,6 +104,10 @@ fn as_jobj(s: JString) -> JObject { unsafe { JObject::from_raw(s.into_raw()) } } +fn as_obj<'a>(s: &str, env: &JNIEnv<'a>) -> JObject<'a> { + as_jobj(env.new_string(s).unwrap()) +} + const CALLBACK_SIG: &str = "(Ljava/lang/Object;)Ljava/lang/Object;"; #[no_mangle] @@ -103,10 +124,10 @@ pub extern "C" fn Java_com_github_opfromthestart_openfunny_Scraper_initImages( .query(&[("page", 1)]) .build() .unwrap(); - log!(env, format!("{req:?}")); + // log!(env, format!("{req:?}")); let json = c.execute(req).unwrap().text().unwrap(); - log!(env, &json); + // log!(env, &json); let parsed: Result = serde_json::from_str(&json); if parsed.is_err() { log!(env, parsed.unwrap_err().to_string()); @@ -116,7 +137,7 @@ pub extern "C" fn Java_com_github_opfromthestart_openfunny_Scraper_initImages( let u = get_int(&mut env, IMAGES.lock().unwrap().items.len() as i32); - log!(env, "Main call"); + // log!(env, "Main call"); match env.call_method(callback, "apply", CALLBACK_SIG, &[JValue::Object(&u)]) { Ok(_) => (), @@ -136,6 +157,30 @@ pub extern "C" fn Java_com_github_opfromthestart_openfunny_Scraper_imageCount( IMAGES.lock().unwrap().items.len() as i32 } +fn load_imgs<'a>(ind: usize, env: &mut JNIEnv<'a>) { + let c = reqwest::blocking::Client::new(); + let page = ind / 10 + 1; + + let json = c + .get(format!("https://ifunny.co/api/v1/feeds/featured")) + .headers(HEADER.clone()) + .query(&[("page", page)]) + .send() + .unwrap(); + + let images: Result = serde_json::from_str(&json.text().unwrap()); + if images.is_err() { + log!(env, images.unwrap_err().to_string()); + return; + } + let images = images.unwrap(); + IMAGES + .lock() + .unwrap() + .items + .extend(images.items.into_iter()) +} + #[no_mangle] #[allow(non_snake_case)] pub extern "C" fn Java_com_github_opfromthestart_openfunny_Scraper_getImage<'local>( @@ -147,7 +192,7 @@ pub extern "C" fn Java_com_github_opfromthestart_openfunny_Scraper_getImage<'loc if num < 0 { return; } - log!(env, "anything?"); + // log!(env, "anything?"); let ind = num as usize; let exists = { IMAGEBUFFERS.lock().unwrap().get(&ind).is_some() }; let b = if exists { @@ -161,27 +206,7 @@ pub extern "C" fn Java_com_github_opfromthestart_openfunny_Scraper_getImage<'loc env.byte_array_from_slice(&[]).unwrap() } else { if cur_img <= ind { - let c = reqwest::blocking::Client::new(); - let page = ind / 10 + 1; - - let json = c - .get("https://ifunny.co/api/v1/feeds/featured") - .headers(HEADER.clone()) - .query(&[("page", page)]) - .send() - .unwrap(); - - let images: Result = serde_json::from_str(&json.text().unwrap()); - if images.is_err() { - log!(env, images.unwrap_err().to_string()); - return; - } - let images = images.unwrap(); - IMAGES - .lock() - .unwrap() - .items - .extend(images.items.into_iter()) + load_imgs(ind, &mut env); } let path = &IMAGES.lock().unwrap().items[ind].url; let c = reqwest::blocking::Client::new(); @@ -202,7 +227,117 @@ pub extern "C" fn Java_com_github_opfromthestart_openfunny_Scraper_getImage<'loc } }; - log!(env, "pre call??"); + // log!(env, "pre call??"); + + match env.call_method( + callback, + "apply", + CALLBACK_SIG, + &[JValue::Object(&unsafe { JObject::from_raw(b.into_raw()) })], + ) { + Ok(_) => { + log!(env, "Function good"); + } + Err(e) => { + log!(env, e.to_string()); + } + } + // log!(env, "what??"); +} + +#[no_mangle] +#[allow(non_snake_case)] +pub extern "C" fn Java_com_github_opfromthestart_openfunny_Scraper_getComments<'local>( + mut env: JNIEnv<'local>, + _obj: JObject, + num: jint, + callback: JObject, +) { + if num < 0 { + return; + } + // log!(env, "anything?"); + let ind = num as usize; + let exists = { COMMENTBUFFERS.lock().unwrap().get(&ind).is_some() }; + let b = if exists { + log!(env, "exists"); + let items = COMMENTBUFFERS.lock().unwrap().get(&ind).unwrap().len() as i32; + let comments = env + .new_object_array(items, "java/lang/String", &JObject::null()) + .unwrap(); + + for (i, c) in COMMENTBUFFERS + .lock() + .unwrap() + .get(&ind) + .unwrap() + .iter() + .enumerate() + { + env.set_object_array_element(&comments, i as i32, as_obj(c, &env)) + .unwrap(); + } + comments + } else { + log!(env, "get web"); + let cur_img = IMAGES.lock().unwrap().items.len(); + if cur_img + 10 <= ind { + env.new_object_array(0, "java/lang/Object", &JObject::null()) + .unwrap() + } else { + if cur_img <= ind { + load_imgs(ind, &mut env); + } + let id = IMAGES.lock().unwrap().items[ind].id.clone(); + let path = format!("https://ifunny.co/api/v1/content/{id}/comments?next=0"); + log!(env, &path); + let c = reqwest::blocking::Client::new(); + if let Ok(resp) = c.get(path).headers(HEADER.clone()).send() { + if let Ok(resp_str) = resp.text() { + log!(env, &resp_str); + let comment: Result = serde_json::from_str(&resp_str); + if comment.is_err() { + log!(env, format!("{comment:?}")); + return; + } + let comment = comment.unwrap(); + COMMENTBUFFERS.lock().unwrap().insert( + ind, + comment + .items + .into_iter() + .map(|c| format!("{}:{}", c.user.nick, c.text)) + .collect(), + ); + let items = COMMENTBUFFERS.lock().unwrap().get(&ind).unwrap().len() as i32; + let comments = env + .new_object_array(items, "java/lang/String", &JObject::null()) + .unwrap(); + + for (i, c) in COMMENTBUFFERS + .lock() + .unwrap() + .get(&ind) + .unwrap() + .iter() + .enumerate() + { + env.set_object_array_element(&comments, i as i32, as_obj(c, &env)) + .unwrap(); + } + comments + } else { + env.new_object_array(0, "java/lang/Object", &JObject::null()) + .unwrap() + } + } else { + env.new_object_array(0, "java/lang/Object", &JObject::null()) + .unwrap() + } + } + }; + + // log!(env, "pre call??"); match env.call_method( callback, @@ -217,5 +352,5 @@ pub extern "C" fn Java_com_github_opfromthestart_openfunny_Scraper_getImage<'loc log!(env, e.to_string()); } } - log!(env, "what??"); + // log!(env, "what??"); }