diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1baf4a2..2a3693d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -45,7 +45,6 @@ - + { + private Context context; + private Album album; + private List imageUrls; + private List nums; + private static List loading = new ArrayList<>(); + + public void clearLoad() { + loading.clear(); + } + + public PhotoAdapter(Context context, List imageUrls, List nums, Album a) { + this.context = context; + this.imageUrls = imageUrls; + this.nums = nums; + this.album = a; + } + + @NonNull + @Override + public PhotoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(context).inflate(R.layout.photo_item, parent, false); + return new PhotoViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull PhotoViewHolder holder, @SuppressLint("RecyclerView") int position) { + String imageUrl = imageUrls.get(position); + int num = nums.get(position); + String fileName = "image_" + album.getAlbum_id() + "_" + position + ".jpg"; + File cacheFile = FileUtils.getCacheDir(context, fileName); + + Log.d("HHHHHHHHHH", "Loading image at position: " + loading.toString()); + if (cacheFile.exists() && (!loading.contains(position))) { + Log.d("HHHHHHHHHH", "Loading cached image at position: " + position); + // 加载缓存的图片并压缩到屏幕大小 + Glide.with(context) + .asBitmap() + .load(cacheFile) + .override(holder.itemView.getWidth(), holder.itemView.getHeight()) // 压缩图片到屏幕大小 + .into(new CustomTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, Transition transition) { + Log.d("PhotoAdapter", "Image loaded successfully at position: " + position); + if (!loading.contains(position)) { + loading.add(position); + } + holder.imageView.setImageBitmap(resource); + holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + + // 设置长按监听器 + holder.imageView.setOnLongClickListener(v -> { + saveImageToMediaStore(resource, fileName); + return true; + }); + } + + @Override + public void onLoadCleared(Drawable placeholder) { + Log.d("PhotoAdapter", "Image load cleared at position: " + position); + } + + @Override + public void onLoadFailed(Drawable errorDrawable) { + super.onLoadFailed(errorDrawable); + Log.e("PhotoAdapter", "Image load failed at position: " + position); + } + }); + } else if ((!loading.contains(position))) { + // 从网络加载并处理图片 + Glide.with(context) + .asBitmap() + .load(imageUrl) + .override(holder.itemView.getWidth(), holder.itemView.getHeight()) // 压缩图片到屏幕大小 + .into(new CustomTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, Transition transition) { + Log.d("PhotoAdapter", "Image loaded successfully at position: " + position); + if (!loading.contains(position)) { + loading.add(position); + } + + Bitmap decodedBitmap = decodeImage(resource, num); + holder.imageView.setImageBitmap(decodedBitmap); + holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + + // 保存处理后的图片到缓存 + saveBitmapToCache(decodedBitmap, cacheFile); + + // 设置长按监听器 + holder.imageView.setOnLongClickListener(v -> { + saveImageToMediaStore(decodedBitmap, fileName); + return true; + }); + } + + @Override + public void onLoadCleared(Drawable placeholder) { + Log.d("PhotoAdapter", "Image load cleared at position: " + position); + } + + @Override + public void onLoadFailed(Drawable errorDrawable) { + super.onLoadFailed(errorDrawable); + Log.e("PhotoAdapter", "Image load failed at position: " + position); + } + }); + } + } + + @Override + public int getItemCount() { + return imageUrls.size(); + } + + public static class PhotoViewHolder extends RecyclerView.ViewHolder { + ImageView imageView; + + public PhotoViewHolder(@NonNull View itemView) { + super(itemView); + imageView = itemView.findViewById(R.id.photo); + } + } + + private Bitmap decodeImage(Bitmap imgSrc, int num) { + if (num == 0) { + return imgSrc; + } + + int w = imgSrc.getWidth(); + int h = imgSrc.getHeight(); + + // 创建新的解密图片 + Bitmap imgDecode = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(imgDecode); + + int over = h % num; + for (int i = 0; i < num; i++) { + int move = h / num; + int ySrc = h - (move * (i + 1)) - over; + int yDst = move * i; + + if (i == 0) { + move += over; + } else { + yDst += over; + } + + Rect srcRect = new Rect(0, ySrc, w, ySrc + move); + Rect dstRect = new Rect(0, yDst, w, yDst + move); + + canvas.drawBitmap(imgSrc, srcRect, dstRect, null); + } + + return imgDecode; + } + + private void saveBitmapToCache(Bitmap bitmap, File file) { + OutputStream outputStream = null; + try { + outputStream = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + private void saveImageToMediaStore(Bitmap bitmap, String fileName) { + ContentValues values = new ContentValues(); + values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName); + values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); + values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/FindMaimaiUltra"); + + Uri uri = null; + OutputStream outputStream = null; + + try { + uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + if (uri != null) { + outputStream = context.getContentResolver().openOutputStream(uri); + if (outputStream != null) { + bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream); + Toast.makeText(context, "图片已保存到相册", Toast.LENGTH_SHORT).show(); + } + } + } catch (Exception e) { + e.printStackTrace(); + if (uri != null) { + context.getContentResolver().delete(uri, null, null); + } + Toast.makeText(context, "保存图片失败", Toast.LENGTH_SHORT).show(); + } finally { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + // 添加删除缓存方法 + public void clearCache() { + File cacheDir = FileUtils.getCacheDir(context, ""); + if (cacheDir.exists() && cacheDir.isDirectory()) { + File[] files = cacheDir.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isFile()) { + file.delete(); + } + } + } + } + } +} diff --git a/app/src/main/java/org/astral/findmaimaiultra/adapter/PixivAdapter.java b/app/src/main/java/org/astral/findmaimaiultra/adapter/PixivAdapter.java index 8f62ac0..89920b1 100644 --- a/app/src/main/java/org/astral/findmaimaiultra/adapter/PixivAdapter.java +++ b/app/src/main/java/org/astral/findmaimaiultra/adapter/PixivAdapter.java @@ -1,5 +1,6 @@ package org.astral.findmaimaiultra.adapter; +import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; @@ -49,15 +50,21 @@ public class PixivAdapter extends RecyclerView.Adapter return new ViewHolder(view); } + @SuppressLint("SetTextI18n") @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { IllustData data = dataList.get(position); holder.title.setText(data.getTitle()); // Load image using a library like Glide or Picasso - String imageUrl = "http://43.153.174.191:45678/api/v1/pixiv/toTencent?id=" + data.getId(); - - if (imageUrl != null) { - loadImage(holder.backgroundLayout, imageUrl); + if (data.getUrl().startsWith("JM:")) { + holder.title.setText("[" + data.getId() + "] " +data.getTitle()); + }else if (data.getId().startsWith("Place:")) { + holder.title.setText(data.getTitle() + " - " + data.getAlt()); + }else { + String imageUrl = "http://43.153.174.191:45678/api/v1/pixiv/toTencent?id=" + data.getId(); + if (imageUrl != null) { + loadImage(holder.backgroundLayout, imageUrl); + } } holder.itemView.setOnClickListener(v -> { diff --git a/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/Album.java b/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/Album.java new file mode 100644 index 0000000..7123003 --- /dev/null +++ b/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/Album.java @@ -0,0 +1,153 @@ +package org.astral.findmaimaiultra.been.pixiv.jm; + +import java.io.Serializable; +import java.util.List; + +public class Album { + private String album_id; + private String scramble_id; + private String name; + private int page_count; + private String pub_date; + private String update_date; + private int likes; + private int views; + private int comment_count; + private List works; + private List actors; + private List authors; + private List tags; + private List image_urls; + private List related_list; + private List nums; + + public List getNums() { + return nums; + } + + public void setNums(List nums) { + this.nums = nums; + } + + // Getters and Setters + public String getAlbum_id() { + return album_id; + } + + public void setAlbum_id(String album_id) { + this.album_id = album_id; + } + + public String getScramble_id() { + return scramble_id; + } + + public void setScramble_id(String scramble_id) { + this.scramble_id = scramble_id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getPage_count() { + return page_count; + } + + public void setPage_count(int page_count) { + this.page_count = page_count; + } + + public String getPub_date() { + return pub_date; + } + + public void setPub_date(String pub_date) { + this.pub_date = pub_date; + } + + public String getUpdate_date() { + return update_date; + } + + public void setUpdate_date(String update_date) { + this.update_date = update_date; + } + + public int getLikes() { + return likes; + } + + public void setLikes(int likes) { + this.likes = likes; + } + + public int getViews() { + return views; + } + + public void setViews(int views) { + this.views = views; + } + + public int getComment_count() { + return comment_count; + } + + public void setComment_count(int comment_count) { + this.comment_count = comment_count; + } + + public List getWorks() { + return works; + } + + public void setWorks(List works) { + this.works = works; + } + + public List getActors() { + return actors; + } + + public void setActors(List actors) { + this.actors = actors; + } + + public List getAuthors() { + return authors; + } + + public void setAuthors(List authors) { + this.authors = authors; + } + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public List getImage_urls() { + return image_urls; + } + + public void setImage_urls(List image_urls) { + this.image_urls = image_urls; + } + + public List getRelated_list() { + return related_list; + } + + public void setRelated_list(List related_list) { + this.related_list = related_list; + } +} + diff --git a/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/AlbumItem.java b/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/AlbumItem.java new file mode 100644 index 0000000..2ecfddf --- /dev/null +++ b/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/AlbumItem.java @@ -0,0 +1,23 @@ +package org.astral.findmaimaiultra.been.pixiv.jm; + +public class AlbumItem { + private String album_id; + private String title; + + // Getters and Setters + public String getAlbum_id() { + return album_id; + } + + public void setAlbum_id(String album_id) { + this.album_id = album_id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/RelatedItem.java b/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/RelatedItem.java new file mode 100644 index 0000000..65e622b --- /dev/null +++ b/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/RelatedItem.java @@ -0,0 +1,41 @@ +package org.astral.findmaimaiultra.been.pixiv.jm; + +public class RelatedItem { + private String id; + private String author; + private String name; + private String image; + + // Getters and Setters + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/SearchJM.java b/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/SearchJM.java new file mode 100644 index 0000000..0e4de40 --- /dev/null +++ b/app/src/main/java/org/astral/findmaimaiultra/been/pixiv/jm/SearchJM.java @@ -0,0 +1,17 @@ +package org.astral.findmaimaiultra.been.pixiv.jm; + +import java.util.List; + +public class SearchJM { + private List albums; + + // Getter and Setter + public List getAlbums() { + return albums; + } + + public void setAlbums(List albums) { + this.albums = albums; + } +} + diff --git a/app/src/main/java/org/astral/findmaimaiultra/ui/JMActivity.java b/app/src/main/java/org/astral/findmaimaiultra/ui/JMActivity.java new file mode 100644 index 0000000..4dc76ce --- /dev/null +++ b/app/src/main/java/org/astral/findmaimaiultra/ui/JMActivity.java @@ -0,0 +1,70 @@ +package org.astral.findmaimaiultra.ui; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.FrameLayout; +import android.widget.TextView; +import android.widget.Toast; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.bottomsheet.BottomSheetBehavior; +import com.google.gson.Gson; +import org.astral.findmaimaiultra.R; +import org.astral.findmaimaiultra.adapter.PhotoAdapter; +import org.astral.findmaimaiultra.been.pixiv.jm.Album; + + +public class JMActivity extends AppCompatActivity { + private FrameLayout overlay; + private boolean isOverlayVisible = false; + private BottomSheetBehavior bottomSheetBehavior; + private PhotoAdapter photoAdapter; + @Override + @SuppressLint("MissingInflatedId") + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.jm_dialog); + + initRecyclerView(); + } + + @SuppressLint({"ClickableViewAccessibility", "SetTextI18n"}) + private void initRecyclerView() { + Intent intent = getIntent(); + String res = intent.getStringExtra("album"); + Album a = new Gson().fromJson(res, Album.class); + RecyclerView recyclerView = findViewById(R.id.recyclerView); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + photoAdapter = new PhotoAdapter(this, a.getImage_urls(), a.getNums(), a); + photoAdapter.clearLoad(); + + recyclerView.setAdapter(photoAdapter); + bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet)); + bottomSheetBehavior.setPeekHeight(dpToPx(80)); + TextView menu = findViewById(R.id.menu); + menu.setText(a.getName()); + TextView dec = findViewById(R.id.dec); + dec.setText(a.getAuthors().toString().replaceAll( "\\[","").replaceAll( "]","") + + " / " + a.getActors().toString().replaceAll( "\"","") .replaceAll( "\\[","").replaceAll( "]","") + + " \n " + a.getTags().toString().replaceAll( "\"","") .replaceAll( "\\[","").replaceAll( "]","") + + " \n " + a.getAlbum_id().replaceAll( "\"","").replaceAll( "\\[","").replaceAll( "]","")); + } + public int dpToPx(int dp) { + return (int) (dp * getResources().getDisplayMetrics().density); + } + @Override + protected void onDestroy() { + super.onDestroy(); + if (photoAdapter != null) { + photoAdapter.clearCache(); + } + } +} diff --git a/app/src/main/java/org/astral/findmaimaiultra/ui/pixiv/PixivFragment.java b/app/src/main/java/org/astral/findmaimaiultra/ui/pixiv/PixivFragment.java index 3cf621a..60f2f62 100644 --- a/app/src/main/java/org/astral/findmaimaiultra/ui/pixiv/PixivFragment.java +++ b/app/src/main/java/org/astral/findmaimaiultra/ui/pixiv/PixivFragment.java @@ -1,21 +1,14 @@ package org.astral.findmaimaiultra.ui.pixiv; -import android.Manifest; import android.annotation.SuppressLint; -import android.app.Activity; import android.content.*; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.drawable.BitmapDrawable; -import android.location.Address; -import android.location.*; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; -import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.util.Log; @@ -23,52 +16,48 @@ import android.view.*; import android.widget.*; import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.SearchView; -import androidx.appcompat.widget.Toolbar; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; -import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.CustomTarget; +import com.bumptech.glide.request.target.Target; +import com.bumptech.glide.request.transition.Transition; import com.google.android.material.button.MaterialButton; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import okhttp3.*; import org.astral.findmaimaiultra.R; -import org.astral.findmaimaiultra.adapter.MusicRatingAdapter; import org.astral.findmaimaiultra.adapter.PixivAdapter; -import org.astral.findmaimaiultra.adapter.PlaceAdapter; -import org.astral.findmaimaiultra.been.*; +import org.astral.findmaimaiultra.been.Place; +import org.astral.findmaimaiultra.been.pixiv.jm.Album; +import org.astral.findmaimaiultra.been.pixiv.jm.AlbumItem; +import org.astral.findmaimaiultra.been.pixiv.jm.SearchJM; import org.astral.findmaimaiultra.been.pixiv.model.IllustData; import org.astral.findmaimaiultra.been.pixiv.model.PixivResponse; import org.astral.findmaimaiultra.been.pixiv.model.pages.PagePixivResponse; import org.astral.findmaimaiultra.been.pixiv.model.pages.photo.Photo; import org.astral.findmaimaiultra.been.pixiv.model.pages.photo.PhotoResponse; -import org.astral.findmaimaiultra.been.pixiv.model.pages.photo.Urls; -import org.astral.findmaimaiultra.databinding.FragmentHomeBinding; import org.astral.findmaimaiultra.databinding.FragmentPixivBinding; -import org.astral.findmaimaiultra.ui.MainActivity; +import org.astral.findmaimaiultra.ui.JMActivity; import org.astral.findmaimaiultra.ui.PageActivity; import org.astral.findmaimaiultra.ui.home.HomeViewModel; -import org.astral.findmaimaiultra.utill.AddressParser; import org.astral.findmaimaiultra.utill.SharedViewModel; import org.jetbrains.annotations.NotNull; import java.io.*; import java.lang.reflect.Type; -import java.text.SimpleDateFormat; +import java.net.URL; import java.util.*; import java.util.concurrent.TimeUnit; + public class PixivFragment extends Fragment { private RecyclerView recyclerView; private Handler handler = new Handler(Looper.getMainLooper()); @@ -142,19 +131,29 @@ public class PixivFragment extends Fragment { recyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); recyclerView.setAdapter(adapter); // 设置搜索框的查询监听器 + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { // 显示 Snackbar 提示“正在搜索” + RadioGroup radioGroup = binding.radioGroup2; + + Snackbar snackbar = Snackbar.make(root, "正在搜索...", Snackbar.LENGTH_INDEFINITE); snackbar.setAnchorView(searchView); // 设置 Snackbar 锚定到搜索框 snackbar.show(); - + //获取单选框 + int checkedRadioButtonId = radioGroup.getCheckedRadioButtonId(); adapter.update(new ArrayList<>()); adapter.notifyDataSetChanged(); - // 当用户提交查询时调用 fetchData 方法 - fetchData(query, 1, snackbar); + if (checkedRadioButtonId == R.id.pb) { + fetchData(query, 1, snackbar); + } else if (checkedRadioButtonId == R.id.jmb) { + fetchDataJM(query, 1, snackbar); + }else if (checkedRadioButtonId == R.id.maimai) { + fetchDataMai(query, 1, snackbar); + } // 显示搜索结果布局,隐藏 RecyclerView path1.setVisibility(View.GONE); path2.setVisibility(View.VISIBLE); @@ -171,7 +170,106 @@ public class PixivFragment extends Fragment { return root; } + private void fetchDataMai(String query, int i, Snackbar snackbar) { + OkHttpClient client = new OkHttpClient(); + Request request = new Request.Builder() + .url("http://mai.godserver.cn:11451/api/mai/v1/searchAll?query=" + query ) + .build(); + snackbar.dismiss(); + client.newCall(request).enqueue(new Callback() { + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + String json = response.body().string(); + if (response.isSuccessful()) { + List dataList = new Gson().fromJson(json, new TypeToken>() { + }.getType()); + List dataList2 = new ArrayList<>(); + for (Place place : dataList) { + IllustData illustData = new IllustData(); + illustData.setId("Place:"+place.getId()); + illustData.setTitle(place.getName()); + illustData.setAlt(place.getProvince()); + illustData.setUrl(place.getAddress()); + illustData.setDescription(new Gson().toJson(place,Place.class)); + dataList2.add(illustData); + } + handler.post(() -> { + path2.setVisibility(View.VISIBLE); + recyclerView.setVisibility(View.VISIBLE); + adapter.update(dataList2); + adapter.notifyDataSetChanged(); + }); + } + } + + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + + } + }); + } + + private void fetchDataJM(String query, int i, Snackbar snackbar) { + OkHttpClient client = new OkHttpClient(); + int type =0; + Request request = new Request.Builder() + .url("http://jm.godserver.cn:35621/search?search_query=" + query + "&page=1") + .build(); + if (query.matches("\\d+")) { + request = new Request.Builder() + .url("jm.godserver.cn:35621/album/" + query + "/") + .build(); + type = 1; + } + snackbar = Snackbar.make(requireView(), "加载中", Snackbar.LENGTH_SHORT); + snackbar.show(); + int finalType = type; + Snackbar finalSnackbar = snackbar; + client.newCall(request).enqueue(new Callback() { + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + String json = response.body().string(); + if (response.isSuccessful()) { + if(finalType == 0) { + System.out.println(json); + Gson gson = new Gson(); + Type listType = new TypeToken>() {}.getType(); + List albumItems = gson.fromJson(json, listType); + + List dataList = new ArrayList<>(); + for (AlbumItem item : albumItems) { + IllustData illustData = new IllustData(); + illustData.setId(item.getAlbum_id()); + illustData.setTitle(item.getTitle()); + illustData.setUrl("JM:" + item.getAlbum_id()); + System.out.println(item.getAlbum_id()); + dataList.add(illustData); + } + + handler.post(() -> { + path2.setVisibility(View.VISIBLE); + recyclerView.setVisibility(View.VISIBLE); + adapter.update(dataList); + adapter.notifyDataSetChanged(); + // 隐藏 Snackbar + finalSnackbar.dismiss(); + }); + }else if (finalType == 1) { + Album albumItem = new Gson().fromJson(json, Album.class); + openJMProject(albumItem); + } + } + } + + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + + } + }); + } + private void fetchData(String word, int page, Snackbar snackbar) { + OkHttpClient client = new OkHttpClient(); //设置超时时间60s client.newBuilder().connectTimeout(60, TimeUnit.SECONDS); @@ -257,6 +355,18 @@ public class PixivFragment extends Fragment { @SuppressLint("MissingInflatedId") private void openIllustData(IllustData illustData) { + if (illustData.getUrl().startsWith("JM:")) { + Snackbar snackbar = Snackbar.make(binding.getRoot(), "正在获取数据", Snackbar.LENGTH_LONG); + snackbar.show(); + openJM(illustData,snackbar); + return; + } + if (illustData.getId().startsWith("Place:")) { + Snackbar snackbar = Snackbar.make(binding.getRoot(), "正在获取数据", Snackbar.LENGTH_SHORT); + snackbar.show(); + openPlace(illustData); + return; + } MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext()); builder.setTitle(illustData.getTitle()); Log.d("PixivFragment", "openIllustData: " + illustData.getTitle()); @@ -354,6 +464,159 @@ public class PixivFragment extends Fragment { // 显示对话框 dialog.show(); } + + private void openPlace(IllustData illustData) { + Place place = new Gson().fromJson(illustData.getDescription(), Place.class); + Intent intent = new Intent(context, PageActivity.class); + intent.putExtra("id", place.getId()); + intent.putExtra("name", place.getName()); + intent.putExtra("address", place.getAddress()); + intent.putExtra("province", place.getProvince()); + intent.putExtra("city", place.getCity()); + intent.putExtra("area", place.getArea()); + intent.putExtra("x", place.getX()); + intent.putExtra("y", place.getY()); + intent.putExtra("count", place.getCount()); + intent.putExtra("bad", place.getBad()); + intent.putExtra("good", place.getGood()); + intent.putExtra("num", place.getNum()); + intent.putExtra("numJ", place.getNumJ()); + intent.putExtra("meituan", place.getMeituan_link()); + intent.putExtra("douyin", place.getDouyin_link()); + startActivity(intent); + } + + private void openJM(IllustData illustData,Snackbar snackbar) { + MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext()); + builder.setTitle(illustData.getTitle()); + //snackbar长显示 + snackbar = Snackbar.make(requireView(), "正在加载", Snackbar.LENGTH_INDEFINITE); + snackbar.show(); + OkHttpClient httpClient = new OkHttpClient(); + //配置超时 + httpClient.newBuilder().connectTimeout(120, TimeUnit.SECONDS); + httpClient.newBuilder().readTimeout(120, TimeUnit.SECONDS); + httpClient.newBuilder().writeTimeout(120, TimeUnit.SECONDS); + + Request request = new Request.Builder() + .url("http://jm.godserver.cn:35621/album/" + illustData.getId() + "/") + .build(); + Log.d("MainLaunch", "http://jm.godserver.cn:35621/album/" + illustData.getId() + "/"); + //配置超时 + + Snackbar finalSnackbar = snackbar; + httpClient.newCall(request).enqueue(new Callback() { + + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + String res = response.body().string(); + if (response.isSuccessful()) { + Log.d("PixivFragment", "onResponse: " + res); + finalSnackbar.dismiss(); + Album a = new Gson().fromJson(res, Album.class); + openJMProject(a); + } + } + + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + handler.post(()->{ + Toast.makeText(requireContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); + finalSnackbar.dismiss(); + }); + Log.d("PixivFragment", "onFailure: " + e.getMessage()); + } + }); + } + private Bitmap decodeImage(Bitmap imgSrc, int num) { + if (num == 0) { + return imgSrc; + } + + int w = imgSrc.getWidth(); + int h = imgSrc.getHeight(); + + // 创建新的解密图片 + Bitmap imgDecode = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(imgDecode); + + int over = h % num; + for (int i = 0; i < num; i++) { + int move = h / num; + int ySrc = h - (move * (i + 1)) - over; + int yDst = move * i; + + if (i == 0) { + move += over; + } else { + yDst += over; + } + + Rect srcRect = new Rect(0, ySrc, w, ySrc + move); + Rect dstRect = new Rect(0, yDst, w, yDst + move); + + canvas.drawBitmap(imgSrc, srcRect, dstRect, null); + } + + return imgDecode; + } + + private void loadImageFromUrl(String url, int num, LinearLayout li) { + // 使用 Glide 加载图片 + Glide.with(requireContext()) + .asBitmap() + .load(url) + .into(new CustomTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + Bitmap decodedBitmap = decodeImage(resource, num); // 假设 num 为 4,根据实际情况调整 + + // 更新 UI + handler.post(() -> { + ImageView photoView = new ImageView(getContext()); + photoView.setImageBitmap(decodedBitmap); + photoView.setScaleType(ImageView.ScaleType.CENTER_CROP); // 设置图片缩放类型 + photoView.setAdjustViewBounds(true); // 调整视图边界 + + // 设置布局参数 + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + layoutParams.setMargins(0, 0, 0, 0); // 设置间距为0 + photoView.setLayoutParams(layoutParams); + + li.addView(photoView); + Log.d("t111111111", url); + }); + } + + @Override + public void onLoadCleared(@Nullable Drawable placeholder) { + // 处理加载清除的情况 + } + + @Override + public void onLoadFailed(@Nullable Drawable errorDrawable) { + super.onLoadFailed(errorDrawable); + handler.post(() -> { + Toast.makeText(requireContext(), "图片加载失败", Toast.LENGTH_SHORT).show(); + }); + } + }); + } + + + @SuppressLint("MissingInflatedId") + private void openJMProject(Album a) { + Intent intent = new Intent(requireContext(), JMActivity.class); + intent.putExtra("album", new Gson().toJson(a)); + startActivity(intent); + } + + + + private void download(String url) { //复制 ClipboardManager clipboardManager = (ClipboardManager) requireContext().getSystemService(Context.CLIPBOARD_SERVICE); diff --git a/app/src/main/java/org/astral/findmaimaiultra/utill/FileUtils.java b/app/src/main/java/org/astral/findmaimaiultra/utill/FileUtils.java new file mode 100644 index 0000000..0a1f479 --- /dev/null +++ b/app/src/main/java/org/astral/findmaimaiultra/utill/FileUtils.java @@ -0,0 +1,16 @@ +package org.astral.findmaimaiultra.utill; + +import android.content.Context; +import android.os.Environment; + +import java.io.File; + +public class FileUtils { + public static File getCacheDir(Context context, String fileName) { + File cacheDir = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "FindMaimaiUltra"); + if (!cacheDir.exists()) { + cacheDir.mkdirs(); + } + return new File(cacheDir, fileName); + } +} diff --git a/app/src/main/res/anim/slide_down.xml b/app/src/main/res/anim/slide_down.xml new file mode 100644 index 0000000..ec800ee --- /dev/null +++ b/app/src/main/res/anim/slide_down.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/anim/slide_up.xml b/app/src/main/res/anim/slide_up.xml new file mode 100644 index 0000000..f3e81d3 --- /dev/null +++ b/app/src/main/res/anim/slide_up.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/layout/fragment_pixiv.xml b/app/src/main/res/layout/fragment_pixiv.xml index 180b49c..8f2c51e 100644 --- a/app/src/main/res/layout/fragment_pixiv.xml +++ b/app/src/main/res/layout/fragment_pixiv.xml @@ -1,4 +1,3 @@ - + + + + + + + + + + diff --git a/app/src/main/res/layout/jm_dialog.xml b/app/src/main/res/layout/jm_dialog.xml new file mode 100644 index 0000000..70dfdcd --- /dev/null +++ b/app/src/main/res/layout/jm_dialog.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/overlay_layout.xml b/app/src/main/res/layout/overlay_layout.xml new file mode 100644 index 0000000..4166282 --- /dev/null +++ b/app/src/main/res/layout/overlay_layout.xml @@ -0,0 +1,11 @@ + + + + diff --git a/app/src/main/res/layout/photo_item.xml b/app/src/main/res/layout/photo_item.xml new file mode 100644 index 0000000..4972841 --- /dev/null +++ b/app/src/main/res/layout/photo_item.xml @@ -0,0 +1,11 @@ + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5edf175..9695eb7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,7 +39,7 @@ FindMaimaiDX Reisa 设置 - pixiv + Image \ No newline at end of file