callback);
- /**
- * Generates 3D model from image
- *
- * @param image Base64 encoded image
- *
- * Requires authorization
- */
- @Method(requestType = RequestType.POST, value = "models/generate")
- void modelsGenerate(@Arg("") String image, @Header("Content-Type") String type, APICallback callback);
-
- /**
- * Gets remaining model generations count
- *
- * Requires authorization
- */
- @Method("models/getRemainingCount")
- void modelsGetRemainingCount(APICallback callback);
-
/**
* Destroys token
*
@@ -158,66 +141,13 @@ public interface CloudAPI extends APIRunner {
public String bearer;
}
- final class UserFeatures {
+ final class AuthToken {
/**
- * Which level is required for early access
+ * Bearer token
*/
- public int earlyAccessLevel;
-
- /**
- * Which level is required for data sync
- */
- public int syncRequiredLevel;
-
- /**
- * Which level is required for AI model generator
- */
- public int aiGeneratorRequiredLevel;
-
- /**
- * Models per month max
- */
- public int aiGeneratorModelsPerMonth;
-
- /**
- * Url at which user should be redirected for info about how to restore a subscription
- */
- public String alreadySubscribedInfoUrl;
-
- /**
- * List of subscription levels
- */
- public List levels = new ArrayList<>();
+ public String bearer;
}
- final class SubscriptionLevel {
- /**
- * Int representation
- */
- public int level;
-
- /**
- * Title of this level
- */
- public String title;
-
- /**
- * Price of this level
- */
- public String price;
-
- /**
- * Url at which user should be redirected for purchase
- */
- public String subscribeOrUpgradeUrl;
-
- /**
- * Url at which user should be redirected for managing the subscription
- */
- public String manageUrl;
- }
-
-
final class UserInfo {
/**
* User's id
@@ -235,10 +165,6 @@ public interface CloudAPI extends APIRunner {
@Nullable
public String avatarUrl;
- /**
- * Current subscription level
- */
- public int currentLevel;
}
@@ -259,15 +185,4 @@ public interface CloudAPI extends APIRunner {
public long maxSize;
}
- final class ModelsRemainingCount {
- /**
- * Used generations
- */
- public int used;
-
- /**
- * Max available generations
- */
- public int max;
- }
}
diff --git a/app/src/main/java/com/dark98/santoku/cloud/CloudController.java b/app/src/main/java/com/dark98/santoku/cloud/CloudController.java
index f62f2ca..a7488d3 100644
--- a/app/src/main/java/com/dark98/santoku/cloud/CloudController.java
+++ b/app/src/main/java/com/dark98/santoku/cloud/CloudController.java
@@ -21,9 +21,7 @@ import ru.ytkab0bp.sapil.APIRequestHandle;
import com.dark98.santoku.R;
import com.dark98.santoku.Santoku;
import com.dark98.santoku.components.BeamAlertDialogBuilder;
-import com.dark98.santoku.events.CloudFeaturesUpdatedEvent;
import com.dark98.santoku.events.CloudLoginStateUpdatedEvent;
-import com.dark98.santoku.events.CloudModelsRemainingCountUpdatedEvent;
import com.dark98.santoku.events.CloudSyncFinishedEvent;
import com.dark98.santoku.events.CloudUserInfoUpdatedEvent;
import com.dark98.santoku.events.NeedDismissSnackbarEvent;
@@ -35,19 +33,13 @@ import com.dark98.santoku.utils.ViewUtils;
import com.dark98.santoku.view.SnackbarsLayout;
public class CloudController {
- public final static String USER_INFO_AI_GEN_TAG = "ai_gen_user_info";
public final static String CLOUD_SYNC_TAG = "cloud_sync";
private final static String TAG = "cloud";
private final static long MIN_SYNC_DELTA = 5 * 60 * 1000L; // Once in 5 minutes
- private final static long MIN_SYNC_FEATURES_DELTA = 12 * 60 * 60 * 1000L; // Once in 12 hours
-
private static boolean isSyncInProgress;
private static CloudAPI.UserInfo userInfo;
- private static CloudAPI.UserFeatures userFeatures;
- private static int modelsUsed;
- private static int modelsMaxGenerations;
private static boolean isLoggingIn;
private static APIRequestHandle beginLoginHandle;
private static String loginSessionId;
@@ -86,31 +78,21 @@ public class CloudController {
private static Gson gson = new Gson();
public static void initCached() {
- if (Prefs.getCloudCachedUserFeatures() != null) {
- userFeatures = gson.fromJson(Prefs.getCloudCachedUserFeatures(), CloudAPI.UserFeatures.class);
- }
if (Prefs.getCloudAPIToken() != null) {
if (Prefs.getCloudCachedUserInfo() != null) {
userInfo = gson.fromJson(Prefs.getCloudCachedUserInfo(), CloudAPI.UserInfo.class);
- modelsUsed = Prefs.getCloudCachedUsedModels();
- modelsMaxGenerations = Prefs.getCloudCachedMaxModels();
}
}
}
public static void init() {
- long now = Santoku.TRUE_TIME.now().getTime();
- boolean needSyncInfo = userFeatures == null || now - Prefs.getCloudLastFeaturesSync() > MIN_SYNC_FEATURES_DELTA;
- if (needSyncInfo) {
- checkUserFeatures();
- }
-
if (Prefs.getCloudAPIToken() != null) {
- if (needSyncInfo || userInfo == null) {
+ long now = Santoku.TRUE_TIME.now().getTime();
+ if (userInfo == null) {
loadUserInfo();
}
- if (!needSyncInfo && userInfo != null && isSyncAvailable() && Prefs.isCloudProfileSyncEnabled()) {
+ if (userInfo != null && isSyncAvailable() && Prefs.isCloudProfileSyncEnabled()) {
if (now - Prefs.getCloudLastSync() > MIN_SYNC_DELTA) {
syncData();
}
@@ -137,7 +119,6 @@ public class CloudController {
} else {
Prefs.setCloudCachedUserInfo(gson.toJson(userInfo));
- Santoku.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(USER_INFO_AI_GEN_TAG));
Santoku.EVENT_BUS.fireEvent(new CloudUserInfoUpdatedEvent());
if (isLoggingIn) {
@@ -148,9 +129,7 @@ public class CloudController {
if (isSyncAvailable() && Prefs.isCloudProfileSyncEnabled()) {
syncData();
}
- checkGeneratorRemaining();
}
- Prefs.setCloudLastFeaturesSync(Santoku.TRUE_TIME.now().getTime());
}
@Override
@@ -205,77 +184,23 @@ public class CloudController {
}
public static void logout() {
+ CloudAPI.INSTANCE.logout(response -> {});
Prefs.setCloudAPIToken(null);
userInfo = null;
Santoku.EVENT_BUS.fireEvent(new CloudLoginStateUpdatedEvent());
Santoku.EVENT_BUS.fireEvent(new CloudUserInfoUpdatedEvent());
- CloudAPI.INSTANCE.logout(response -> {});
- }
-
- public static void checkGeneratorRemaining() {
- CloudAPI.INSTANCE.modelsGetRemainingCount(new APICallback() {
- @Override
- public void onResponse(CloudAPI.ModelsRemainingCount response) {
- modelsUsed = response.used;
- modelsMaxGenerations = response.max;
- Prefs.setCloudCachedUsedMaxModels(modelsUsed, modelsMaxGenerations);
- Santoku.EVENT_BUS.fireEvent(new CloudModelsRemainingCountUpdatedEvent());
- }
-
- @Override
- public void onException(Exception e) {
- Log.e(TAG, "Failed to check remaining models", e);
- ViewUtils.postOnMainThread(CloudController::checkGeneratorRemaining, 15000);
- }
- });
- }
-
- public static void checkUserFeatures() {
- CloudAPI.INSTANCE.userGetFeatures(new APICallback() {
- @Override
- public void onResponse(CloudAPI.UserFeatures response) {
- userFeatures = response;
- Prefs.setCloudCachedUserFeatures(gson.toJson(userFeatures));
- if (Prefs.getCloudAPIToken() == null) {
- Prefs.setCloudLastFeaturesSync(Santoku.TRUE_TIME.now().getTime());
- }
- Santoku.EVENT_BUS.fireEvent(new CloudFeaturesUpdatedEvent());
- }
-
- @Override
- public void onException(Exception e) {
- Log.e(TAG, "Failed to get user features", e);
- ViewUtils.postOnMainThread(CloudController::checkUserFeatures, 15000);
- }
- });
}
public static CloudAPI.UserInfo getUserInfo() {
return userInfo;
}
- public static CloudAPI.UserFeatures getUserFeatures() {
- return userFeatures;
- }
-
public static boolean hasAccountFeatures() {
- return userFeatures != null && userFeatures.levels != null && !userFeatures.levels.isEmpty();
+ return true;
}
public static boolean isSyncAvailable() {
- return Prefs.getCloudAPIToken() != null && userInfo != null && userFeatures != null && userInfo.currentLevel >= userFeatures.syncRequiredLevel;
- }
-
- public static boolean needShowAIGenerator() {
- return userFeatures != null && userFeatures.aiGeneratorRequiredLevel >= 0;
- }
-
- public static int getGeneratedModels() {
- return modelsUsed;
- }
-
- public static int getMaxGeneratedModels() {
- return modelsMaxGenerations;
+ return Prefs.getCloudAPIToken() != null && userInfo != null;
}
private static void downloadData(long lastModified) {
diff --git a/app/src/main/java/com/dark98/santoku/components/ChangeLogBottomSheet.java b/app/src/main/java/com/dark98/santoku/components/ChangeLogBottomSheet.java
index a8f2d00..8d85ddb 100644
--- a/app/src/main/java/com/dark98/santoku/components/ChangeLogBottomSheet.java
+++ b/app/src/main/java/com/dark98/santoku/components/ChangeLogBottomSheet.java
@@ -1,9 +1,7 @@
package com.dark98.santoku.components;
import android.content.Context;
-import android.content.Intent;
import android.graphics.drawable.GradientDrawable;
-import android.net.Uri;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
@@ -13,13 +11,9 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ScrollView;
-import android.widget.Scroller;
import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.core.graphics.ColorUtils;
-import androidx.viewpager.widget.PagerAdapter;
-import androidx.viewpager.widget.ViewPager;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
@@ -28,26 +22,17 @@ import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Locale;
-import ru.ytkab0bp.eventbus.EventHandler;
-import com.dark98.santoku.BeamServerData;
import com.dark98.santoku.R;
import com.dark98.santoku.Santoku;
-import com.dark98.santoku.events.BeamServerDataUpdatedEvent;
import com.dark98.santoku.theme.ThemesRepo;
import com.dark98.santoku.utils.ViewUtils;
import com.dark98.santoku.view.BeamButton;
-import com.dark98.santoku.view.BoostySubsView;
public class ChangeLogBottomSheet extends BottomSheetDialog {
- private BoostySubsView subsView;
private ScrollView scrollView;
- private ViewPager pager;
public ChangeLogBottomSheet(@NonNull Context context) {
super(context);
@@ -77,18 +62,6 @@ public class ChangeLogBottomSheet extends BottomSheetDialog {
}});
fl.addView(titleA);
- TextView titleB = new TextView(context);
- titleB.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
- titleB.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
- titleB.setText(R.string.ChangelogBoosty);
- titleB.setTextColor(ThemesRepo.getColor(R.attr.textColorOnAccent));
- titleB.setGravity(Gravity.CENTER);
- titleB.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) {{
- leftMargin = rightMargin = ViewUtils.dp(21);
- }});
- titleB.setAlpha(0f);
- fl.addView(titleB);
-
ll.addView(fl);
scrollView = new ScrollView(context);
@@ -120,112 +93,11 @@ public class ChangeLogBottomSheet extends BottomSheetDialog {
scrollView.addView(text);
DisplayMetrics dm = context.getResources().getDisplayMetrics();
+ ll.addView(scrollView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) (dm.heightPixels * 0.45f)));
- pager = new ViewPager(context) {{
- try {
- Field scroller = ViewPager.class.getDeclaredField("mScroller");
- scroller.setAccessible(true);
-
- Scroller mScroller = new Scroller(getContext(), ViewUtils.CUBIC_INTERPOLATOR::getInterpolation);
- scroller.set(this, mScroller);
- } catch (Exception ignored) {}
- }};
- pager.setAdapter(new PagerAdapter() {
- @Override
- public int getCount() {
- return BeamServerData.isBoostyAvailable() ? 2 : 1;
- }
-
- @NonNull
- @Override
- public Object instantiateItem(@NonNull ViewGroup container, int position) {
- View v;
- if (position == 0) {
- v = scrollView;
- } else {
- LinearLayout ll = new LinearLayout(context);
- ll.setOrientation(LinearLayout.VERTICAL);
-
- TextView subtitle = new TextView(context);
- subtitle.setTextColor(ThemesRepo.getColor(R.attr.textColorOnAccent));
- subtitle.setText(R.string.ChangelogBoostyDescription);
- subtitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
- subtitle.setGravity(Gravity.CENTER);
- subtitle.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
- subtitle.setPadding(ViewUtils.dp(12), 0, ViewUtils.dp(12), 0);
- ll.addView(subtitle);
-
- subsView = new BoostySubsView(context);
- if (Santoku.SERVER_DATA != null) {
- List list = new ArrayList<>(Santoku.SERVER_DATA.boostySubscribers);
- Collections.shuffle(list);
- subsView.setStrings(list);
- }
- ll.addView(subsView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
-
- TextView subscribeButton = new TextView(context);
- subscribeButton.setText(R.string.IntroBoostySupport);
- subscribeButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
- subscribeButton.setTextColor(ThemesRepo.getColor(R.attr.boostyColorTop));
- subscribeButton.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
- subscribeButton.setGravity(Gravity.CENTER);
- subscribeButton.setPadding(ViewUtils.dp(12), ViewUtils.dp(8), ViewUtils.dp(12), ViewUtils.dp(8));
- subscribeButton.setOnClickListener(v2 -> context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://boosty.to/ytkab0bp"))));
- ll.addView(subscribeButton, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
-
- v = ll;
- }
-
- container.addView(v);
- return v;
- }
-
- @Override
- public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
- container.removeView((View) object);
- }
-
- @Override
- public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
- return view == object;
- }
- });
BeamButton btn = new BeamButton(context);
- pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
- @Override
- public void onPageSelected(int position) {
- super.onPageSelected(position);
- if (position == pager.getAdapter().getCount() - 1) {
- btn.setText(R.string.ChangelogOK);
- } else {
- btn.setText(R.string.ChangelogNext);
- }
- }
-
- private int[] colors = new int[2];
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- float pr = position == 0 ? positionOffset : 1f;
- colors[0] = ColorUtils.blendARGB(ThemesRepo.getColor(R.attr.dialogBackground), ThemesRepo.getColor(R.attr.boostyColorTop), pr);
- colors[1] = ColorUtils.blendARGB(ThemesRepo.getColor(R.attr.dialogBackground), ThemesRepo.getColor(R.attr.boostyColorBottom), pr);
- gd.setColors(colors);
- titleA.setAlpha(1f - pr);
- titleA.setTranslationX(-titleA.getWidth() * 0.25f * pr);
- titleB.setAlpha(pr);
- titleB.setTranslationX(titleB.getWidth() * 0.25f * (1f - pr));
- btn.setColor(ColorUtils.blendARGB(ThemesRepo.getColor(android.R.attr.colorAccent), ThemesRepo.getColor(R.attr.boostyColorTop), pr));
- }
- });
- ll.addView(pager, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) (dm.heightPixels * 0.45f)));
-
- btn.setText(R.string.ChangelogNext);
- btn.setOnClickListener(v -> {
- if (pager.getCurrentItem() != pager.getAdapter().getCount() - 1) {
- pager.setCurrentItem(pager.getCurrentItem() + 1);
- } else {
- dismiss();
- }
- });
+ btn.setText(R.string.ChangelogOK);
+ btn.setOnClickListener(v -> dismiss());
ll.addView(btn, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(48)) {{
leftMargin = topMargin = rightMargin = bottomMargin = ViewUtils.dp(12);
}});
@@ -233,18 +105,6 @@ public class ChangeLogBottomSheet extends BottomSheetDialog {
ll.setFitsSystemWindows(true);
setContentView(ll);
- Santoku.EVENT_BUS.registerListener(this);
- setOnDismissListener(dialog -> Santoku.EVENT_BUS.unregisterListener(this));
- }
-
- @EventHandler(runOnMainThread = true)
- public void onDataUpdated(BeamServerDataUpdatedEvent e) {
- if (Santoku.SERVER_DATA != null) {
- List list = new ArrayList<>(Santoku.SERVER_DATA.boostySubscribers);
- Collections.shuffle(list);
- subsView.setStrings(list);
- }
- pager.getAdapter().notifyDataSetChanged();
}
@Override
diff --git a/app/src/main/java/com/dark98/santoku/components/CloudManageBottomSheet.java b/app/src/main/java/com/dark98/santoku/components/CloudManageBottomSheet.java
index 3918b67..395a328 100644
--- a/app/src/main/java/com/dark98/santoku/components/CloudManageBottomSheet.java
+++ b/app/src/main/java/com/dark98/santoku/components/CloudManageBottomSheet.java
@@ -10,7 +10,6 @@ import android.util.TypedValue;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.LinearLayout;
-import android.widget.Space;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -26,7 +25,7 @@ import java.util.List;
import com.dark98.santoku.R;
import com.dark98.santoku.Santoku;
-import com.dark98.santoku.cloud.CloudAPI;
+import com.dark98.santoku.BuildConfig;
import com.dark98.santoku.cloud.CloudController;
import com.dark98.santoku.events.NeedDismissSnackbarEvent;
import com.dark98.santoku.recycler.PreferenceSwitchItem;
@@ -65,77 +64,56 @@ public class CloudManageBottomSheet extends BottomSheetDialog {
}});
ll.addView(title);
- TextView description = new TextView(context);
- description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
- description.setText(context.getString(R.string.SettingsCloudManageLoggedInAs, CloudController.getUserInfo().displayName));
- description.setTextColor(ThemesRepo.getColor(android.R.attr.textColorSecondary));
- description.setGravity(Gravity.CENTER);
- description.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) {{
- leftMargin = rightMargin = ViewUtils.dp(21);
- topMargin = ViewUtils.dp(8);
+ List items = new ArrayList<>();
+ items.add(new PreferenceSwitchItem()
+ .setIcon(R.drawable.sync_outline_28)
+ .setTitle(context.getString(R.string.SettingsCloudManageFeatureCloudSync))
+ .setValueProvider(Prefs::isCloudProfileSyncEnabled)
+ .setChangeListener((buttonView, isChecked) -> {
+ Prefs.setCloudProfileSyncEnabled(isChecked);
+ if (isChecked) {
+ CloudController.notifyDataChanged();
+ } else {
+ Santoku.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(CloudController.CLOUD_SYNC_TAG));
+ }
+ }));
+ RecyclerView recyclerView = new RecyclerView(context);
+ recyclerView.setLayoutManager(new LinearLayoutManager(context));
+ recyclerView.setBackground(ViewUtils.createRipple(0, ColorUtils.setAlphaComponent(ThemesRepo.getColor(android.R.attr.colorControlHighlight), 0x10), 16));
+ SimpleRecyclerAdapter adapter = new SimpleRecyclerAdapter();
+ adapter.setItems(items);
+ recyclerView.setAdapter(adapter);
+ ll.addView(recyclerView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) {{
+ topMargin = ViewUtils.dp(16);
+ leftMargin = rightMargin = ViewUtils.dp(16);
}});
- ll.addView(description);
- int currentLevel = CloudController.getUserInfo().currentLevel;
- CloudAPI.SubscriptionLevel lvl = null;
- CloudAPI.UserFeatures features = CloudController.getUserFeatures();
- for (CloudAPI.SubscriptionLevel level : features.levels) {
- if (level.level != -1 && level.level <= currentLevel && (lvl == null || level.level > lvl.level)) {
- lvl = level;
+ TextView manageButton = new TextView(context);
+ SpannableStringBuilder sb = SpannableStringBuilder.valueOf(context.getString(R.string.SettingsCloudManageSubscription)).append(" ");
+ Drawable dr = ContextCompat.getDrawable(context, R.drawable.external_link_outline_24);
+ int size = ViewUtils.dp(16);
+ dr.setBounds(0, 0, size, size);
+ sb.append("d", new TextColorImageSpan(dr, ViewUtils.dp(2f)), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
+ manageButton.setText(sb);
+ manageButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
+ manageButton.setTextColor(ThemesRepo.getColor(android.R.attr.textColorSecondary));
+ manageButton.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
+ manageButton.setGravity(Gravity.CENTER);
+ manageButton.setPadding(ViewUtils.dp(12), ViewUtils.dp(8), ViewUtils.dp(12), ViewUtils.dp(8));
+ manageButton.setBackground(ViewUtils.createRipple(ThemesRepo.getColor(android.R.attr.colorControlHighlight), 16));
+ manageButton.setOnClickListener(v -> {
+ String url = BuildConfig.BEAM_BASE_URL_PROD + "/account";
+ String token = Prefs.getCloudAPIToken();
+ if (token != null) {
+ Uri uri = Uri.parse(url);
+ url = uri.buildUpon().appendQueryParameter("token", token).build().toString();
}
- }
-
- if (lvl != null) {
- List items = new ArrayList<>();
- if (currentLevel >= features.syncRequiredLevel) {
- items.add(new PreferenceSwitchItem()
- .setIcon(R.drawable.sync_outline_28)
- .setTitle(context.getString(R.string.SettingsCloudManageFeatureCloudSync))
- .setValueProvider(Prefs::isCloudProfileSyncEnabled)
- .setChangeListener((buttonView, isChecked) -> {
- Prefs.setCloudProfileSyncEnabled(isChecked);
- if (isChecked) {
- CloudController.notifyDataChanged();
- } else {
- Santoku.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(CloudController.CLOUD_SYNC_TAG));
- }
- }));
- }
- if (!items.isEmpty()) {
- RecyclerView recyclerView = new RecyclerView(context);
- recyclerView.setLayoutManager(new LinearLayoutManager(context));
- recyclerView.setBackground(ViewUtils.createRipple(0, ColorUtils.setAlphaComponent(ThemesRepo.getColor(android.R.attr.colorControlHighlight), 0x10), 16));
- SimpleRecyclerAdapter adapter = new SimpleRecyclerAdapter();
- adapter.setItems(items);
- recyclerView.setAdapter(adapter);
- ll.addView(recyclerView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) {{
- topMargin = ViewUtils.dp(16);
- leftMargin = rightMargin = ViewUtils.dp(16);
- }});
- }
-
- TextView manageButton = new TextView(context);
- SpannableStringBuilder sb = SpannableStringBuilder.valueOf(context.getString(R.string.SettingsCloudManageSubscription)).append(" ");
- Drawable dr = ContextCompat.getDrawable(context, R.drawable.external_link_outline_24);
- int size = ViewUtils.dp(16);
- dr.setBounds(0, 0, size, size);
- sb.append("d", new TextColorImageSpan(dr, ViewUtils.dp(2f)), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
- manageButton.setText(sb);
- manageButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
- manageButton.setTextColor(ThemesRepo.getColor(android.R.attr.textColorSecondary));
- manageButton.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
- manageButton.setGravity(Gravity.CENTER);
- manageButton.setPadding(ViewUtils.dp(12), ViewUtils.dp(8), ViewUtils.dp(12), ViewUtils.dp(8));
- manageButton.setBackground(ViewUtils.createRipple(ThemesRepo.getColor(android.R.attr.colorControlHighlight), 16));
- CloudAPI.SubscriptionLevel finalLvl = lvl;
- manageButton.setOnClickListener(v -> v.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(finalLvl.manageUrl))));
- ll.addView(manageButton, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(48)) {{
- leftMargin = rightMargin = ViewUtils.dp(16);
- topMargin = bottomMargin = ViewUtils.dp(6);
- }});
- } else {
- ll.addView(new Space(context), new LinearLayout.LayoutParams(0, ViewUtils.dp(16)));
- }
+ v.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
+ });
+ ll.addView(manageButton, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(48)) {{
+ leftMargin = rightMargin = ViewUtils.dp(16);
+ topMargin = bottomMargin = ViewUtils.dp(6);
+ }});
TextView buttonView = new TextView(context);
buttonView.setText(R.string.SettingsCloudManageButtonLogOut);
diff --git a/app/src/main/java/com/dark98/santoku/components/bed_menu/FileMenu.java b/app/src/main/java/com/dark98/santoku/components/bed_menu/FileMenu.java
index 827c104..e8e2c30 100644
--- a/app/src/main/java/com/dark98/santoku/components/bed_menu/FileMenu.java
+++ b/app/src/main/java/com/dark98/santoku/components/bed_menu/FileMenu.java
@@ -4,7 +4,6 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
-import android.provider.MediaStore;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
@@ -15,7 +14,6 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
-import androidx.core.content.FileProvider;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.RecyclerView;
@@ -33,20 +31,13 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import ru.ytkab0bp.eventbus.EventHandler;
-import com.dark98.santoku.BeamServerData;
-import com.dark98.santoku.BuildConfig;
import com.dark98.santoku.MainActivity;
import com.dark98.santoku.R;
-import com.dark98.santoku.SetupActivity;
import com.dark98.santoku.Santoku;
-import com.dark98.santoku.cloud.CloudController;
import com.dark98.santoku.components.BeamAlertDialogBuilder;
import com.dark98.santoku.components.UnfoldMenu;
import com.dark98.santoku.components.WebViewMenu;
import com.dark98.santoku.config.ConfigObject;
-import com.dark98.santoku.events.CloudFeaturesUpdatedEvent;
-import com.dark98.santoku.events.CloudModelsRemainingCountUpdatedEvent;
-import com.dark98.santoku.events.NeedDismissAIGeneratorMenu;
import com.dark98.santoku.events.NeedDismissCalibrationsMenu;
import com.dark98.santoku.events.NeedDismissSnackbarEvent;
import com.dark98.santoku.events.NeedSnackbarEvent;
@@ -61,11 +52,9 @@ import com.dark98.santoku.slic3r.Bed3D;
import com.dark98.santoku.slic3r.Slic3rRuntimeError;
import com.dark98.santoku.theme.BeamTheme;
import com.dark98.santoku.theme.ThemesRepo;
-import com.dark98.santoku.utils.Prefs;
import com.dark98.santoku.utils.ViewUtils;
import com.dark98.santoku.view.DividerView;
import com.dark98.santoku.view.FadeRecyclerView;
-import com.dark98.santoku.view.SegmentsView;
import com.dark98.santoku.view.SnackbarsLayout;
public class FileMenu extends ListBedMenu {
@@ -126,29 +115,6 @@ public class FileMenu extends ListBedMenu {
}
}),
new SpaceItem(portrait ? ViewUtils.dp(3) : 0, portrait ? 0 : ViewUtils.dp(3))));
- if (BeamServerData.isBoostyAvailable() && CloudController.needShowAIGenerator()) {
- list.add(new BedMenuItem(R.string.MenuFileAIGenerator, R.drawable.picture_stack_outline_28).setShiny(true).onClick(view -> {
- if (Prefs.getCloudAPIToken() == null || CloudController.getUserInfo() != null && CloudController.getMaxGeneratedModels() == 0) {
- Context ctx = view.getContext();
- ctx.startActivity(new Intent(ctx, SetupActivity.class).putExtra(SetupActivity.EXTRA_CLOUD_PROFILE, true));
- return;
- }
- if (CloudController.getUserInfo() == null) {
- Santoku.EVENT_BUS.fireEvent(new NeedSnackbarEvent(SnackbarsLayout.Type.LOADING, R.string.MenuFileAIGeneratorPleaseWaitSetup).tag(CloudController.USER_INFO_AI_GEN_TAG));
- ViewUtils.postOnMainThread(() -> {
- if (CloudController.getUserInfo() == null) {
- Santoku.EVENT_BUS.fireEvent(new NeedDismissSnackbarEvent(CloudController.USER_INFO_AI_GEN_TAG));
- Santoku.EVENT_BUS.fireEvent(new NeedSnackbarEvent(SnackbarsLayout.Type.ERROR, R.string.MenuFileAIGeneratorErrorNotLoadedUserAccount));
- } else {
- fragment.showUnfoldMenu(new AIGeneratorMenu(), view);
- }
- }, 2500);
- return;
- }
-
- fragment.showUnfoldMenu(new AIGeneratorMenu(), view);
- }));
- }
list.addAll(Arrays.asList(
new BedMenuItem(R.string.MenuFileCalibrations, R.drawable.wrench_outline_28).setSingleLine(true).onClick(v -> {
if (!fragment.getGlView().getRenderer().getBed().isValid()) {
@@ -263,10 +229,7 @@ public class FileMenu extends ListBedMenu {
public void onObjectsChanged(ObjectsListChangedEvent e) {
((BedMenuItem) adapter.getItems().get(1)).setEnabled(hasSelection());
adapter.notifyItemChanged(1);
-
- int i = 8 - (BeamServerData.isBoostyAvailable() && CloudController.needShowAIGenerator() ? 0 : 1);
- ((BedMenuItem) adapter.getItems().get(i)).setEnabled(hasModel());
- adapter.notifyItemChanged(i);
+ updateModelItems();
}
@EventHandler(runOnMainThread = true)
@@ -275,147 +238,17 @@ public class FileMenu extends ListBedMenu {
adapter.notifyItemChanged(1);
}
- @EventHandler(runOnMainThread = true)
- public void onFeaturedUpdated(CloudFeaturesUpdatedEvent e) {
- adapter.setItems(onCreateItems(wasPortrait));
- }
-
- public final static class AIGeneratorMenu extends UnfoldMenu {
- private TextView remainingView;
- private SegmentsView segmentsView;
-
- @Override
- public int getRequestedSize(FrameLayout into, boolean portrait) {
- return (int) (portrait ? ViewUtils.dp(52) + ViewUtils.dp(60) * 2 + ViewUtils.dp(28) + ViewUtils.dp(18) + ViewUtils.dp(2) : into.getWidth() * 0.6f);
+ private void updateModelItems() {
+ int idx = -1;
+ for (int j = adapter.getItems().size() - 1; j >= 0; j--) {
+ if (adapter.getItems().get(j) instanceof BedMenuItem) {
+ idx = j;
+ break;
+ }
}
-
- @Override
- protected View onCreateView(Context ctx, boolean portrait) {
- LinearLayout ll = new LinearLayout(ctx);
- ll.setOrientation(LinearLayout.VERTICAL);
-
- RecyclerView rv = new FadeRecyclerView(ctx);
- rv.setOverScrollMode(View.OVER_SCROLL_NEVER);
- SimpleRecyclerAdapter adapter = new SimpleRecyclerAdapter();
- adapter.setItems(Arrays.asList(
- new PreferenceItem().setIcon(R.drawable.camera_outline_28).setTitle(ctx.getString(R.string.MenuFileAIGeneratorFromCamera)).setOnClickListener(v -> {
- if (CloudController.getGeneratedModels() >= CloudController.getMaxGeneratedModels()) {
- Santoku.EVENT_BUS.fireEvent(new NeedSnackbarEvent(SnackbarsLayout.Type.ERROR, R.string.MenuFileAIGeneratorNoGenerationsLeft));
- return;
- }
- if (MainActivity.IS_GENERATING_AI_MODEL) {
- Santoku.EVENT_BUS.fireEvent(new NeedSnackbarEvent(SnackbarsLayout.Type.WARNING, R.string.MenuFileAIGeneratorAlreadyGenerating));
- return;
- }
- if (ctx instanceof MainActivity) {
- try {
- MainActivity.aiTempFile = File.createTempFile("ai_capture", ".jpg");
- Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- i.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(ctx, BuildConfig.APPLICATION_ID + ".provider", MainActivity.aiTempFile));
- i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- ((MainActivity) ctx).startActivityForResult(i, MainActivity.REQUEST_CODE_AI_GENERATOR_TAKE_PHOTO);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }),
- new PreferenceItem().setIcon(R.drawable.picture_outline_28).setTitle(ctx.getString(R.string.MenuFileAIGeneratorFromGallery)).setOnClickListener(v -> {
- if (CloudController.getGeneratedModels() >= CloudController.getMaxGeneratedModels()) {
- Santoku.EVENT_BUS.fireEvent(new NeedSnackbarEvent(SnackbarsLayout.Type.ERROR, R.string.MenuFileAIGeneratorNoGenerationsLeft));
- return;
- }
- if (MainActivity.IS_GENERATING_AI_MODEL) {
- Santoku.EVENT_BUS.fireEvent(new NeedSnackbarEvent(SnackbarsLayout.Type.WARNING, R.string.MenuFileAIGeneratorAlreadyGenerating));
- return;
- }
- if (ctx instanceof MainActivity) {
- Intent intent = new Intent();
- intent.setType("image/*");
- intent.setAction(Intent.ACTION_GET_CONTENT);
- ((MainActivity) ctx).startActivityForResult(Intent.createChooser(intent, ""), MainActivity.REQUEST_CODE_AI_GENERATOR_CHOOSE_PHOTO);
- }
- })
- ));
- rv.setAdapter(adapter);
- ll.addView(rv, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
-
- ll.addView(new DividerView(ctx), new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(1f)));
-
- remainingView = new TextView(ctx);
- remainingView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
- remainingView.setGravity(Gravity.CENTER);
- remainingView.setTextColor(ThemesRepo.getColor(android.R.attr.textColorSecondary));
- ll.addView(remainingView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(18)) {{
- topMargin = ViewUtils.dp(8);
- }});
-
- segmentsView = new SegmentsView(ctx) {
- @Override
- protected int onGetColor(int i) {
- return i == 1 ? ThemesRepo.getColor(android.R.attr.textColorSecondary) : ThemesRepo.getColor(android.R.attr.colorAccent);
- }
- };
- ll.addView(segmentsView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(12)) {{
- leftMargin = rightMargin = ViewUtils.dp(12);
- topMargin = bottomMargin = ViewUtils.dp(8);
- }});
- updateRemaining();
-
- ll.addView(new DividerView(ctx), new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(1f)));
-
- LinearLayout toolbar = new LinearLayout(ctx);
- toolbar.setPadding(ViewUtils.dp(12), 0, ViewUtils.dp(12), 0);
- toolbar.setOrientation(LinearLayout.HORIZONTAL);
- toolbar.setGravity(Gravity.CENTER_VERTICAL);
- toolbar.setBackground(ViewUtils.createRipple(ThemesRepo.getColor(android.R.attr.colorControlHighlight), 0));
- toolbar.setOnClickListener(v -> dismiss());
-
- ImageView icon = new ImageView(ctx);
- icon.setImageResource(R.drawable.arrow_left_outline_28);
- icon.setColorFilter(ThemesRepo.getColor(android.R.attr.textColorSecondary));
- toolbar.addView(icon, new LinearLayout.LayoutParams(ViewUtils.dp(28), ViewUtils.dp(28)));
-
- TextView title = new TextView(ctx);
- title.setText(R.string.MenuOrientationPositionBack);
- title.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
- title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
- title.setTextColor(ThemesRepo.getColor(android.R.attr.textColorPrimary));
- toolbar.addView(title, new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f) {{
- leftMargin = ViewUtils.dp(12);
- }});
- ll.addView(toolbar, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(52)));
- return ll;
- }
-
- @Override
- protected void onCreate() {
- super.onCreate();
-
- Santoku.EVENT_BUS.registerListener(this);
- ViewUtils.postOnMainThread(() -> segmentsView.startAnimation(), 50);
- }
-
- @EventHandler(runOnMainThread = true)
- public void onDismiss(NeedDismissAIGeneratorMenu e) {
- dismiss();
- }
-
- @EventHandler(runOnMainThread = true)
- public void onRemainingUpdated(CloudModelsRemainingCountUpdatedEvent e) {
- updateRemaining();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
-
- Santoku.EVENT_BUS.unregisterListener(this);
- }
-
- private void updateRemaining() {
- int rev = CloudController.getMaxGeneratedModels() - CloudController.getGeneratedModels();
- remainingView.setText(Santoku.INSTANCE.getString(R.string.MenuFileAIGeneratorRemaining, rev, CloudController.getMaxGeneratedModels()));
- segmentsView.setValues(new float[]{0, rev / (float) CloudController.getMaxGeneratedModels(), 1});
+ if (idx != -1) {
+ ((BedMenuItem) adapter.getItems().get(idx)).setEnabled(hasModel());
+ adapter.notifyItemChanged(idx);
}
}
diff --git a/app/src/main/java/com/dark98/santoku/events/BeamServerDataUpdatedEvent.java b/app/src/main/java/com/dark98/santoku/events/BeamServerDataUpdatedEvent.java
deleted file mode 100644
index 23508af..0000000
--- a/app/src/main/java/com/dark98/santoku/events/BeamServerDataUpdatedEvent.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.dark98.santoku.events;
-
-import ru.ytkab0bp.eventbus.Event;
-
-@Event
-public class BeamServerDataUpdatedEvent {}
diff --git a/app/src/main/java/com/dark98/santoku/events/CloudFeaturesUpdatedEvent.java b/app/src/main/java/com/dark98/santoku/events/CloudFeaturesUpdatedEvent.java
deleted file mode 100644
index 2452f21..0000000
--- a/app/src/main/java/com/dark98/santoku/events/CloudFeaturesUpdatedEvent.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.dark98.santoku.events;
-
-import ru.ytkab0bp.eventbus.Event;
-
-@Event
-public class CloudFeaturesUpdatedEvent {}
diff --git a/app/src/main/java/com/dark98/santoku/events/CloudModelsRemainingCountUpdatedEvent.java b/app/src/main/java/com/dark98/santoku/events/CloudModelsRemainingCountUpdatedEvent.java
deleted file mode 100644
index 65aead1..0000000
--- a/app/src/main/java/com/dark98/santoku/events/CloudModelsRemainingCountUpdatedEvent.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.dark98.santoku.events;
-
-import ru.ytkab0bp.eventbus.Event;
-
-@Event
-public class CloudModelsRemainingCountUpdatedEvent {}
diff --git a/app/src/main/java/com/dark98/santoku/events/NeedDismissAIGeneratorMenu.java b/app/src/main/java/com/dark98/santoku/events/NeedDismissAIGeneratorMenu.java
deleted file mode 100644
index a9ee98a..0000000
--- a/app/src/main/java/com/dark98/santoku/events/NeedDismissAIGeneratorMenu.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.dark98.santoku.events;
-
-import ru.ytkab0bp.eventbus.Event;
-
-@Event
-public class NeedDismissAIGeneratorMenu {}
\ No newline at end of file
diff --git a/app/src/main/java/com/dark98/santoku/fragment/SettingsFragment.java b/app/src/main/java/com/dark98/santoku/fragment/SettingsFragment.java
index 19e0f04..c0cc6ae 100644
--- a/app/src/main/java/com/dark98/santoku/fragment/SettingsFragment.java
+++ b/app/src/main/java/com/dark98/santoku/fragment/SettingsFragment.java
@@ -20,15 +20,14 @@ import java.util.Collections;
import java.util.List;
import ru.ytkab0bp.eventbus.EventHandler;
-import com.dark98.santoku.BeamServerData;
import com.dark98.santoku.R;
import com.dark98.santoku.SetupActivity;
import com.dark98.santoku.Santoku;
import com.dark98.santoku.components.BeamAlertDialogBuilder;
import com.dark98.santoku.components.BeamColorPickerPopUp;
import com.dark98.santoku.config.ConfigObject;
-import com.dark98.santoku.events.BeamServerDataUpdatedEvent;
import com.dark98.santoku.events.CloudUserInfoUpdatedEvent;
+import com.dark98.santoku.cloud.CloudController;
import com.dark98.santoku.recycler.PreferenceItem;
import com.dark98.santoku.theme.BeamTheme;
import com.dark98.santoku.theme.ThemesRepo;
@@ -46,7 +45,7 @@ public class SettingsFragment extends ProfileListFragment {
@Override
protected List getConfigItems() {
return Arrays.asList(
- BeamServerData.isCloudAvailable() ? new OptionElement(SPECIAL_TYPE_CLOUD_HEADER).setOnClick(() -> {
+ CloudController.hasAccountFeatures() ? new OptionElement(SPECIAL_TYPE_CLOUD_HEADER).setOnClick(() -> {
Activity act = (Activity) getContext();
act.startActivity(new Intent(act, SetupActivity.class).putExtra(SetupActivity.EXTRA_CLOUD_PROFILE, true));
}) : null,
@@ -112,7 +111,7 @@ public class SettingsFragment extends ProfileListFragment {
BeamTheme.LIGHT.colors.put(android.R.attr.colorAccent, Prefs.getAccentColor());
BeamTheme.DARK.colors.put(android.R.attr.colorAccent, Prefs.getAccentColor());
ThemesRepo.invalidate((Activity) getContext());
- recyclerView.getAdapter().notifyItemChanged(2 - (BeamServerData.isCloudAvailable() ? 0 : 1));
+ recyclerView.getAdapter().notifyItemChanged(2 - (CloudController.hasAccountFeatures() ? 0 : 1));
}
})
.setNegativeButtonText(getContext().getString(R.string.SettingsInterfaceColorReset))
@@ -135,7 +134,7 @@ public class SettingsFragment extends ProfileListFragment {
Prefs.setRenderScale(variants[which]);
dialog.dismiss();
// I'm too lazy to calculate real position for now
- recyclerView.getAdapter().notifyItemChanged(4 - (BeamServerData.isCloudAvailable() ? 0 : 1));
+ recyclerView.getAdapter().notifyItemChanged(4 - (CloudController.hasAccountFeatures() ? 0 : 1));
})
.show();
})),
@@ -143,18 +142,6 @@ public class SettingsFragment extends ProfileListFragment {
Activity act = (Activity) getContext();
act.startActivity(new Intent(act, SetupActivity.class).putExtra(SetupActivity.EXTRA_ABOUT, true));
}),
- new OptionElement(R.drawable.telegram, getContext().getString(R.string.SettingsTelegram)).setColor(R.attr.telegramColor, false).setOnClick(() -> {
- Activity act = (Activity) getContext();
- act.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/ytkab0bp_channel")));
- }),
- BeamServerData.isBoostyAvailable() ? new OptionElement(R.drawable.boosty, getContext().getString(R.string.SettingsBoosty)).setColor(R.attr.boostyColorTop, true).setOnClick(() -> {
- Activity act = (Activity) getContext();
- act.startActivity(new Intent(act, SetupActivity.class).putExtra(SetupActivity.EXTRA_BOOSTY_ONLY, true));
- }) : null,
- new OptionElement(R.drawable.k3d_logo_new_14, getContext().getString(R.string.SettingsK3D)).setColor(R.attr.k3dColor, true).setOnClick(() -> {
- Activity act = (Activity) getContext();
- act.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/K_3_D")));
- }),
new OptionElement(R.drawable.refresh_outline_28, getContext().getString(R.string.SettingsResetToDefault)).setColor(R.attr.textColorNegative, false).setOnClick(() -> {
Context ctx = getContext();
if (ctx instanceof Activity) {
@@ -177,14 +164,9 @@ public class SettingsFragment extends ProfileListFragment {
);
}
- @EventHandler(runOnMainThread = true)
- public void onDataUpdated(BeamServerDataUpdatedEvent e) {
- setConfigItems(getConfigItems());
- }
-
@EventHandler(runOnMainThread = true)
public void onUserInfoUpdated(CloudUserInfoUpdatedEvent e) {
- if (BeamServerData.isCloudAvailable()) {
+ if (CloudController.hasAccountFeatures()) {
recyclerView.getAdapter().notifyItemChanged(0);
}
}
diff --git a/app/src/main/java/com/dark98/santoku/theme/BeamTheme.java b/app/src/main/java/com/dark98/santoku/theme/BeamTheme.java
index 9e54aa1..c9d2181 100644
--- a/app/src/main/java/com/dark98/santoku/theme/BeamTheme.java
+++ b/app/src/main/java/com/dark98/santoku/theme/BeamTheme.java
@@ -20,10 +20,6 @@ public class BeamTheme {
colors.put(R.attr.dividerContrastColor, 0xffcccccc);
colors.put(R.attr.dialogBackground, 0xffffffff);
colors.put(R.attr.switchThumbUncheckedColor, 0xffeef2f3);
- colors.put(R.attr.boostyColorTop, 0xfff06e2a);
- colors.put(R.attr.boostyColorBottom, 0xff884725);
- colors.put(R.attr.telegramColor, 0xff27a7e7);
- colors.put(R.attr.k3dColor, 0xff039045);
colors.put(R.attr.modelHoverColor, 0xffffffff);
colors.put(R.attr.textColorNegative, 0xffff464a);
@@ -73,7 +69,6 @@ public class BeamTheme {
colors.put(R.attr.bedContourlinesColor, 0x40ffffff);
colors.put(R.attr.backgroundColorTop, 0xff292929);
colors.put(R.attr.backgroundColorBottom, 0xff181818);
- colors.put(R.attr.boostyColorBottom, 0xff884725);
colors.put(R.attr.xTrackColor, 0xffee0000);
colors.put(R.attr.yTrackColor, 0xff00ee00);
diff --git a/app/src/main/java/com/dark98/santoku/utils/Prefs.java b/app/src/main/java/com/dark98/santoku/utils/Prefs.java
index 2f2ad1d..fe1a4d0 100644
--- a/app/src/main/java/com/dark98/santoku/utils/Prefs.java
+++ b/app/src/main/java/com/dark98/santoku/utils/Prefs.java
@@ -47,31 +47,6 @@ public class Prefs {
mPrefs.edit().putBoolean("scale_linked", v).apply();
}
- public static long getLastCheckedInfo() {
- return mPrefs.getLong("last_checked_info", 0);
- }
-
- public static void setLastCheckedInfo() {
- mPrefs.edit().putLong("last_checked_info", System.currentTimeMillis()).apply();
- }
-
- // Only used for displaying Boosty info, nothing more
- public static boolean isRussianIP() {
- return mPrefs.getBoolean("russian_ip", false);
- }
-
- public static void setRussianIP(boolean v) {
- mPrefs.edit().putBoolean("russian_ip", v).apply();
- }
-
- public static void setBeamServerData(String data) {
- mPrefs.edit().putString("beam_server_data", data).apply();
- }
-
- public static String getBeamServerData() {
- return mPrefs.getString("beam_server_data", "{}");
- }
-
public static int getCameraControlMode() {
return mPrefs.getInt("camera_control_mode", mPrefs.getBoolean("rotation_enabled", true) ? CAMERA_CONTROL_MODE_ROTATE_MOVE : CAMERA_CONTROL_MODE_MOVE_ONLY);
}
@@ -161,40 +136,6 @@ public class Prefs {
e.apply();
}
- public static int getCloudCachedUsedModels() {
- return mPrefs.getInt("cloud_cached_models_used", 0);
- }
-
- public static int getCloudCachedMaxModels() {
- return mPrefs.getInt("cloud_cached_models_max", 50);
- }
-
- public static void setCloudCachedUsedMaxModels(int used, int max) {
- mPrefs.edit().putInt("cloud_cached_models_used", used).putInt("cloud_cached_models_max", max).apply();
- }
-
- public static String getCloudCachedUserFeatures() {
- return mPrefs.getString("cloud_cached_user_features", null);
- }
-
- public static void setCloudCachedUserFeatures(String features) {
- SharedPreferences.Editor e = mPrefs.edit();
- if (features == null) {
- e.remove("cloud_cached_user_features");
- } else {
- e.putString("cloud_cached_user_features", features);
- }
- e.apply();
- }
-
- public static long getCloudLastFeaturesSync() {
- return mPrefs.getLong("cloud_last_features_sync", 0);
- }
-
- public static void setCloudLastFeaturesSync(long ls) {
- mPrefs.edit().putLong("cloud_last_features_sync", ls).apply();
- }
-
public static long getCloudLastSync() {
return mPrefs.getLong("cloud_last_sync", 0);
}
diff --git a/app/src/main/java/com/dark98/santoku/view/BoostySubsView.java b/app/src/main/java/com/dark98/santoku/view/BoostySubsView.java
deleted file mode 100644
index d599df3..0000000
--- a/app/src/main/java/com/dark98/santoku/view/BoostySubsView.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.dark98.santoku.view;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.util.SparseArray;
-import android.view.View;
-
-import androidx.core.math.MathUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.dark98.santoku.R;
-import com.dark98.santoku.theme.ThemesRepo;
-import com.dark98.santoku.utils.ViewUtils;
-
-public class BoostySubsView extends View {
- private TextPaint paint = new TextPaint();
-
- private List strings = new ArrayList<>();
- private SparseArray ellipsizedStrings = new SparseArray<>();
- private int index;
- private float progress;
- private long lastUpdated;
- private int firstHeight;
-
- private Rect rect = new Rect();
-
- public BoostySubsView(Context context) {
- super(context);
-
- paint.setTextSize(ViewUtils.dp(20));
- paint.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
- updateColors();
- }
-
- public void setStrings(List strings) {
- this.strings = strings;
- ellipsizedStrings.clear();
- index = 0;
- progress = 0;
- if (!strings.isEmpty()) {
- String str = strings.get(index);
- paint.getTextBounds(str, 0, str.length(), rect);
- firstHeight = rect.height();
- }
- invalidate();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- long dt = Math.min(16, System.currentTimeMillis() - lastUpdated);
- lastUpdated = System.currentTimeMillis();
- if (!strings.isEmpty()) {
- float tY = (ViewUtils.dp(24) + firstHeight) * progress;
- canvas.save();
- canvas.translate(0, -tY);
- float halfHeight = getHeight() / 2f;
- int y = 0;
-
- int i = index;
- while (y <= getHeight() + tY) {
- int j = i;
- while (j < 0) j += strings.size();
- while (j >= strings.size()) j -= strings.size();
-
- CharSequence str = ellipsizedStrings.get(j);
- if (str == null) {
- ellipsizedStrings.set(j, str = TextUtils.ellipsize(strings.get(j), paint, getWidth() - getPaddingLeft() - getPaddingRight(), TextUtils.TruncateAt.END));
- }
-
- paint.getTextBounds(str.toString(), 0, str.length(), rect);
- float highlight = (1f - Math.abs((y - tY - firstHeight / 2f - halfHeight) / halfHeight));
- highlight = MathUtils.clamp(highlight, 0, 1);
- paint.setAlpha((int) (0xFF * highlight));
-
- float x = (getWidth() - rect.width()) / 2f;
- canvas.drawText(str, 0, str.length(), x, y, paint);
-
- y += rect.height() + ViewUtils.dp(24);
- i++;
- }
-
- canvas.restore();
-
- progress += dt / 2000f;
- if (progress > 1) {
- progress -= 1f;
- index++;
- index %= strings.size();
-
- String str = strings.get(index);
- paint.getTextBounds(str, 0, str.length(), rect);
- firstHeight = rect.height();
- }
- invalidate();
- }
- }
-
- public void updateColors() {
- paint.setColor(ThemesRepo.getColor(R.attr.textColorOnAccent));
- invalidate();
- }
-}
diff --git a/app/src/main/res/drawable/boosty.xml b/app/src/main/res/drawable/boosty.xml
deleted file mode 100644
index 6c493f1..0000000
--- a/app/src/main/res/drawable/boosty.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/box_heart_outline_28.xml b/app/src/main/res/drawable/box_heart_outline_28.xml
deleted file mode 100644
index 1fffd7b..0000000
--- a/app/src/main/res/drawable/box_heart_outline_28.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/k3d_logo_new_14.png b/app/src/main/res/drawable/k3d_logo_new_14.png
deleted file mode 100644
index bf89245..0000000
Binary files a/app/src/main/res/drawable/k3d_logo_new_14.png and /dev/null differ
diff --git a/app/src/main/res/drawable/telegram.xml b/app/src/main/res/drawable/telegram.xml
deleted file mode 100644
index 73a08ff..0000000
--- a/app/src/main/res/drawable/telegram.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 07bed12..a9c93c4 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -16,19 +16,6 @@
Файл содержит более 500к треугольников. Нарезка может быть медленной.
Загрузка файла…
Убрать модель
- Модель\nпо фото
- Пожалуйста, подождите…
- Ошибка: данные о пользователе пока не загружены.
- Сделать фото
- Выбрать из галереи
- Осталось: %d / %d генераций
- Загрузка изображения…
- Обработка изображения…
- Скачивание модели…
- Не удалось сгенерировать модель
- Модель сохранена как %s.
- Не осталось генераций.
- Уже генерируется другая модель.
Калибров.
K3D Linear Advance
Калибровка Linear/Pressure Advance
@@ -149,8 +136,6 @@
Вам необходимо настроить репозитории или использовать пользовательский профиль.
Профили не настроены
Вы должны выбрать хотя бы один профиль.
- Поддерживается этими замечательными людьми на Boosty:
- Подписаться на Boosty
Далее
Похоже всё настроено.\nПросто нажмите завершить!
Завершить
@@ -163,9 +148,6 @@
Это действие не может быть отменено.
Сохранить
Сохранить профиль?
- Boosty разработчика
- Telegram разработчика
- Чат K3D
Интерфейс
Тема
Системная
@@ -176,7 +158,7 @@
Масштаб разрешения 3D
Может увеличить производительность путём снижения разрешения
О приложении
- v%s\nОсновано на PrusaSlicer\n\nCreated by YTKAB0BP
+ v%s\nОсновано на PrusaSlicer & SliceBeam\n\nCreated by Dark98
%s - Копия
Клон. текущий
Удалить текущий
@@ -184,20 +166,10 @@
Загрузка…
Нажмите для управления
Нажмите чтобы узнать больше
- Аккаунт Beam 3D
+ Аккаунт Santoku
Даёт следующие преимущества:
- Ранний доступ
- Вы можете скачать ранние сборки из чата Telegram для подписчиков
Облачная синхронизация профилей
Храните свои профили в облаке Beam
- ИИ генератор моделей
- %1$d моделей по фото в месяц
- Slice Beam может оставаться бесплатным для всех
- Ваш ник будет написан в списке поддержавших.\nСпасибо за вашу поддержку!
- При подписке на данный уровень вы соглашаетесь с условиями обслуживания.
- Уже подписаны?
- Бесплатно
- Вы подписаны
Будет позже
Условия обслуживания
Настройки аккаунта
@@ -206,9 +178,8 @@
Отменить авторизацию?
Выйти
Вошли как «%1$s»
- Управление подпиской
+ Управление аккаунтом
Список изменений
- Выход данного обновления поддержали:
Далее
ОК
Конвертация профилей, пожалуйста, подождите…
@@ -229,4 +200,4 @@
Оставить локальные профили
Да
Нет
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index e6a533a..7de400e 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -25,10 +25,6 @@
-
-
-
-
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 7572d94..034f7ae 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -17,19 +17,6 @@
File has more than 500k triangles. Processing could be slow.
Loading file…
Remove model
- Model\nfrom photo
- Please wait…
- Error: user info not fetched yet.
- Take a photo
- Choose from gallery
- Remaining: %d / %d generations
- Uploading image…
- Processing image…
- Downloading model…
- Failed to generate model
- Saved model as %s.
- No generations left.
- Already generating another model.
Calibrat.
K3D Linear Advance
Linear/Pressure Advance Calibration
@@ -149,8 +136,6 @@
You must configure repositories or use a custom profile.
No profiles configured
You must select at least one profile.
- Is supported by these awesome people on Boosty:
- Subscribe at Boosty
Next
All seems to be configured.\nJust tap finish!
Finish
@@ -163,9 +148,6 @@
This action can not be undone.
Save
Save profile?
- Developer\'s Boosty
- Developer\'s Telegram
- K3D Chat
Interface
Theme
System
@@ -176,7 +158,7 @@
3D Resolution scale
May improve performance by lowering resolution
About app
- v%s\nBased on PrusaSlicer\n\nCreated by YTKAB0BP
+ v%s\nBased on PrusaSlicer & SliceBeam\n\nCreated by Dark98
%s - Copy
Clone current
Delete current
@@ -184,20 +166,10 @@
Loading…
Tap to manage
Tap to learn more
- Beam 3D Account
- Provides the following benefits:
- Early access
- You can download early builds from Telegram chat for subscribers
+ Santoku Account
+ Cloud account
Cloud profiles sync
Store your profiles in Beam Cloud
- AI model generator
- %1$d models from photo per month
- Slice Beam can remain free for all
- Your nickname will be written in the list of supporters.\nThanks for your support!
- By subscribing to this level you accept terms of service.
- Already subscribed?
- Free
- You are subscribed
Will be later
Terms of service
Account settings
@@ -206,10 +178,15 @@
Cancel login?
Log out
Logged in as «%1$s»
- Manage subscription
+ Manage Account
+ Sign up
+ Email
+ Display name
+ Password
+ Please fill in all fields
+ Sign up failed
+ Show password
Changelog
- Boosty
- The release of this update was supported by:
Next
OK
Converting profiles, please wait…
@@ -230,4 +207,4 @@
Keep local profiles
Yes
No
-
\ No newline at end of file
+
diff --git a/build.gradle b/build.gradle
index 8bb264a..7fa1dc7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -19,4 +19,135 @@ allprojects {
task clean(type: Delete) {
delete rootProject.buildDir
-}
\ No newline at end of file
+}
+
+def loadLocalProperties() {
+ def props = new Properties()
+ def propsFile = rootProject.file("local.properties")
+ if (propsFile.exists()) {
+ propsFile.withInputStream { props.load(it) }
+ }
+ return props
+}
+
+def resolveSdkDir() {
+ def props = loadLocalProperties()
+ return props.getProperty("sdk.dir") ?: System.getenv("ANDROID_SDK_ROOT") ?: System.getenv("ANDROID_HOME")
+}
+
+def isWindows = System.getProperty("os.name").toLowerCase().contains("windows")
+def npmCmd = isWindows ? "npm.cmd" : "npm"
+
+def findWindowsNpm() {
+ def candidates = []
+ def pathEnv = System.getenv("PATH") ?: ""
+ pathEnv.split(";").each { p ->
+ if (!p) return
+ def cmd = new File(p, "npm.cmd")
+ if (cmd.exists()) candidates << cmd
+ def exe = new File(p, "npm.exe")
+ if (exe.exists()) candidates << exe
+ }
+ def nvmHome = System.getenv("NVM_HOME")
+ def nvmSymlink = System.getenv("NVM_SYMLINK")
+ if (nvmSymlink) {
+ def cmd = new File(nvmSymlink, "npm.cmd")
+ if (cmd.exists()) candidates << cmd
+ }
+ if (nvmHome) {
+ def current = new File(nvmHome, "current")
+ if (current.exists()) {
+ def cmd = new File(current, "npm.cmd")
+ if (cmd.exists()) candidates << cmd
+ }
+ def versions = new File(nvmHome)
+ if (versions.exists()) {
+ versions.listFiles()?.findAll { it.isDirectory() }?.each { v ->
+ def cmd = new File(v, "npm.cmd")
+ if (cmd.exists()) candidates << cmd
+ }
+ }
+ }
+ def appData = System.getenv("APPDATA")
+ if (appData) {
+ def cmd = new File(appData, "npm\\npm.cmd")
+ if (cmd.exists()) candidates << cmd
+ }
+ def programFiles = System.getenv("ProgramFiles")
+ if (programFiles) {
+ def cmd = new File(programFiles, "nodejs\\npm.cmd")
+ if (cmd.exists()) candidates << cmd
+ }
+ def localAppData = System.getenv("LOCALAPPDATA")
+ if (localAppData) {
+ def nvmLocal = new File(localAppData, "nvm")
+ if (nvmLocal.exists()) {
+ nvmLocal.listFiles()?.findAll { it.isDirectory() }?.each { v ->
+ def cmd = new File(v, "npm.cmd")
+ if (cmd.exists()) candidates << cmd
+ }
+ }
+ }
+ return candidates.isEmpty() ? null : candidates.first().absolutePath
+}
+
+tasks.register("startBackend", Exec) {
+ workingDir "${rootDir}/backend"
+ if (isWindows) {
+ doFirst {
+ def npmPath = (project.findProperty("npmPath") ?: System.getenv("NPM_PATH"))?.toString()
+ if (!npmPath) {
+ npmPath = findWindowsNpm()
+ }
+ if (!npmPath) {
+ def out = new ByteArrayOutputStream()
+ exec {
+ commandLine "cmd", "/c", "where.exe", "npm"
+ standardOutput = out
+ errorOutput = out
+ ignoreExitValue = true
+ }
+ def line = out.toString().readLines().find { it.toLowerCase().endsWith("npm.cmd") || it.toLowerCase().endsWith("npm.exe") }
+ if (line) {
+ npmPath = line.trim()
+ }
+ }
+ if (!npmPath) {
+ throw new GradleException("npm not found. Set -PnpmPath=... or ensure npm is visible to cmd.exe. If using nvm, try your NVM_HOME version's npm.cmd.")
+ }
+ def nodeModules = new File(workingDir, "node_modules")
+ if (!nodeModules.exists()) {
+ exec {
+ workingDir "${rootDir}/backend"
+ commandLine "cmd", "/c", npmPath, "install"
+ }
+ }
+ commandLine "cmd", "/c", "start", "\"\"", npmPath, "start"
+ }
+ } else {
+ doFirst {
+ def nodeModules = new File(workingDir, "node_modules")
+ if (!nodeModules.exists()) {
+ exec {
+ workingDir "${rootDir}/backend"
+ commandLine "sh", "-c", "${npmCmd} install"
+ }
+ }
+ commandLine "sh", "-c", "${npmCmd} start &"
+ }
+ }
+}
+
+tasks.register("runBackendDebug") {
+ dependsOn(":app:installDebug", "startBackend")
+ doLast {
+ def sdkDir = resolveSdkDir()
+ if (!sdkDir) {
+ throw new GradleException("Missing sdk.dir in local.properties and ANDROID_SDK_ROOT/ANDROID_HOME is not set")
+ }
+ def adb = "${sdkDir}/platform-tools/adb" + (isWindows ? ".exe" : "")
+ exec {
+ commandLine adb, "shell", "am", "start", "-n", "com.dark98.santoku/.MainActivity"
+ }
+ }
+}