Search in sources :

Example 31 with Deck

use of com.ichi2.libanki.Deck in project AnkiChinaAndroid by ankichinateam.

the class CollectionTask method doInBackgroundRenderBrowserQA.

private TaskData doInBackgroundRenderBrowserQA(TaskData param) {
    // TODO: Convert this to accept the following to make thread-safe:
    // (Range<Position>, Function<Position, BrowserCard>)
    Timber.d("doInBackgroundRenderBrowserQA");
    Collection col = getCol();
    List<CardBrowser.CardCache> cards = (List<CardBrowser.CardCache>) param.getObjArray()[0];
    Integer startPos = (Integer) param.getObjArray()[1];
    Integer n = (Integer) param.getObjArray()[2];
    int column1Index = (Integer) param.getObjArray()[3];
    int column2Index = (Integer) param.getObjArray()[4];
    List<Long> invalidCardIds = new ArrayList<>();
    // for each specified card in the browser list
    for (int i = startPos; i < startPos + n; i++) {
        // Stop if cancelled
        if (isCancelled()) {
            Timber.d("doInBackgroundRenderBrowserQA was aborted");
            return null;
        }
        if (i < 0 || i >= cards.size()) {
            continue;
        }
        CardBrowser.CardCache card;
        try {
            card = cards.get(i);
        } catch (IndexOutOfBoundsException e) {
            // we won't reach any more cards.
            continue;
        }
        if (card.isLoaded()) {
            // We've already rendered the answer, we don't need to do it again.
            continue;
        }
        // Extract card item
        try {
            // Ensure that card still exists.
            card.getCard();
        } catch (WrongId e) {
            // #5891 - card can be inconsistent between the deck browser screen and the collection.
            // Realistically, we can skip any exception as it's a rendering task which should not kill the
            // process
            long cardId = card.getId();
            Timber.e(e, "Could not process card '%d' - skipping and removing from sight", cardId);
            invalidCardIds.add(cardId);
            continue;
        }
        // Update item
        card.load(false, column1Index, column2Index);
        float progress = (float) i / n * 100;
        publishProgress(new TaskData((int) progress));
    }
    return new TaskData(new Object[] { cards, invalidCardIds });
}
Also used : ArrayList(java.util.ArrayList) CardBrowser(com.ichi2.anki.CardBrowser) Collection(com.ichi2.libanki.Collection) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) WrongId(com.ichi2.libanki.WrongId)

Example 32 with Deck

use of com.ichi2.libanki.Deck in project AnkiChinaAndroid by ankichinateam.

the class DeckInfoListAdapter method onBindViewHolder.

@Override
public void onBindViewHolder(RecyclerView.ViewHolder tempHolder, int position) {
    if (tempHolder instanceof HeaderViewHolder) {
        HeaderViewHolder holder = (HeaderViewHolder) tempHolder;
        holder.mTextDeckName.setText(mTextDeckName);
        holder.mDeckListHeader.setVisibility(mDeckList.isEmpty() ? View.GONE : View.VISIBLE);
        // holder.mTextCongratsMessage.setText(mTextCongratsMessage);
        holder.mTextDeckDescription.setText(mTextDeckDescription != null && mTextDeckDescription.length() > 0 ? formatDescription(mTextDeckDescription) : "");
        holder.mTextTodayNew.setText(mTextTodayNew);
        holder.mTextTodayRev.setText(mTextTodayRev);
        holder.mTextCountHandled.setText(mTextCountHandled);
        holder.mTextCountLearning.setText(mTextCountLearning);
        holder.mTextCountNew.setText(mTextCountNew);
        holder.mTextCountHard.setText(mTextCountHard);
        holder.mTextTotal.setText(mTextTotal);
        holder.mTextHandledPercent.setText(mTextHandledPercent);
        holder.mTextHandledNum.setText(mTextHandledNum);
        holder.mTextETA.setText(mTextETA);
        holder.mButtonStart.setText(mTextButtonStart);
        holder.mButtonStart.setOnClickListener(mButtonStartClickListener);
        holder.mSelfStudyAskIcon.setOnClickListener(v -> {
            if (mSelfStudyQADialog == null) {
                mSelfStudyQADialog = new Dialog(mContext, R.style.CommonDialogTheme);
                View view = View.inflate(mContext, R.layout.pop_window_self_study_introduce, null);
                mSelfStudyQADialog.setContentView(view);
                Window window = mSelfStudyQADialog.getWindow();
                WindowManager.LayoutParams lps = window.getAttributes();
                lps.width = WindowManager.LayoutParams.MATCH_PARENT;
                window.setAttributes(lps);
                window.setGravity(Gravity.BOTTOM);
                window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
            }
            mSelfStudyQADialog.show();
        });
        holder.mStudyProgress.setProgress(mStudyProgress);
        // holder.mDeckInfoLayout.setVisibility(mDeckInfoLayoutVisible);
        // holder.mTextCongratsMessage.setVisibility(mTextCongratsMessageVisible);
        holder.mTextDeckDescription.setVisibility(mTextDeckDescriptionVisible);
        holder.mButtonStart.setEnabled(mButtonStartEnable);
        holder.mSelfStudyHandle.setTag(SelfStudyActivity.TAB_STUDY_STATE);
        holder.mSelfStudyMark.setTag(SelfStudyActivity.TAB_MARK_STATE);
        holder.mSelfStudyAnswer.setTag(SelfStudyActivity.TAB_ANSWER_STATE);
        holder.mSelfStudyCustom.setTag(SelfStudyActivity.TAB_CUSTOM_STATE);
        holder.mSelfStudyHandle.setOnClickListener(mSelfStudyClickListener);
        holder.mSelfStudyMark.setOnClickListener(mSelfStudyClickListener);
        holder.mSelfStudyAnswer.setOnClickListener(mSelfStudyClickListener);
        holder.mSelfStudyCustom.setOnClickListener(mSelfStudyClickListener);
        holder.mTextStudySetting.setVisibility(mCurrentDeck == null || mCurrentDeck.optInt("dyn", 0) == 1 ? View.GONE : View.VISIBLE);
        holder.mTextStudySetting.setOnClickListener(v -> {
            Intent i = new Intent(mContext, StudySettingActivity.class);
            i.putExtra("did", mCurrentDeck.optLong("id"));
            mContext.startActivityForResultWithAnimation(i, DECK_OPTIONS, ActivityTransitionAnimation.FADE);
        });
        if (AD_IMAGE_URL != null && !AD_IMAGE_URL.isEmpty() && AD_LINK_URL != null && !AD_LINK_URL.isEmpty()) {
            holder.mAdLayout.setVisibility(View.VISIBLE);
            CornerTransform transformation = new CornerTransform(mContext, AdaptionUtil.dip2px(mContext, 9));
            transformation.setExceptCorner(false, false, false, false);
            RequestOptions coverRequestOptions = new RequestOptions().transform(transformation).diskCacheStrategy(// 不做磁盘缓存
            DiskCacheStrategy.NONE).skipMemoryCache(// 不做内存缓存
            true);
            Glide.with(mContext).asBitmap().load(AD_IMAGE_URL).apply(coverRequestOptions).into(holder.mAdImage);
            holder.mAdLayout.setOnClickListener(v -> WebViewActivity.openUrlInApp(mContext, AD_LINK_URL, ""));
        } else {
            holder.mAdLayout.setVisibility(View.GONE);
        }
    } else if (tempHolder instanceof ViewHolder) {
        position--;
        ViewHolder holder = (ViewHolder) tempHolder;
        AbstractDeckTreeNode node = mDeckList.get(position);
        // Set the expander icon and padding according to whether or not there are any subdecks
        RelativeLayout deckLayout = holder.deckLayout;
        // int rightPadding = (int) deckLayout.getResources().getDimension(R.dimen.deck_picker_right_padding);
        if (mHasSubdecks) {
            int smallPadding = (int) deckLayout.getResources().getDimension(R.dimen.deck_picker_left_padding_small);
            deckLayout.setPadding(smallPadding, 0, (int) deckLayout.getResources().getDimension(R.dimen.deck_picker_right_padding), 0);
            holder.deckExpander.setVisibility(View.VISIBLE);
            // Create the correct expander for this deck
            setDeckExpander(holder.deckExpander, holder.indentView, node);
        } else {
            holder.deckExpander.setVisibility(View.GONE);
            int normalPadding = (int) deckLayout.getResources().getDimension(R.dimen.deck_picker_left_padding);
            deckLayout.setPadding(normalPadding, 0, (int) deckLayout.getResources().getDimension(R.dimen.deck_picker_right_padding), 0);
        }
        if (node.hasChildren()) {
            holder.deckExpander.setTag(node.getDid());
            holder.deckExpander.setOnClickListener(mDeckExpanderClickListener);
        } else {
            holder.deckExpander.setOnClickListener(null);
        }
        // holder.deckLayout.setBackgroundResource(mRowCurrentDrawable);
        // Set background colour. The current deck has its own color
        // if (isCurrentlySelectedDeck(node)) {
        // Timber.d("can be shown:%s", node.getDid());
        // Timber.d("mHasSubdecks:%s", node.hasChildren() + "");
        // if (mCurrentIDs.contains(node.getDid())) {
        // holder.deckLayout.setVisibility(View.VISIBLE);
        // holder.deckLayout.setBackgroundResource(mRowCurrentDrawable);
        // if (mPartiallyTransparentForBackground) {
        // setBackgroundAlpha(holder.deckLayout, SELECTED_DECK_ALPHA_AGAINST_BACKGROUND);
        // }
        // } else {
        // holder.deckLayout.setVisibility(View.GONE);
        // CompatHelper.getCompat().setSelectableBackground(holder.deckLayout);
        // }
        // Set deck name and colour. Filtered decks have their own colour
        holder.deckName.setText(node.getLastDeckNameComponent());
        if (mCol.getDecks().isDyn(node.getDid())) {
            holder.deckName.setTextColor(mDeckNameDynColor);
        } else {
            if (node.getDepth() == Decks.path(mCurrentDeck.optString("name")).length) {
                holder.deckName.setTextColor(mDeckNameDefaultColor);
            } else {
                holder.deckName.setTextColor(mDeckNameDefaultColorChild);
            }
        }
        if (node.shouldDisplayCounts()) {
            // holder.deckNew.setText(String.valueOf(node.getNewCount()));
            // holder.deckLearn.setText(String.valueOf(node.getLrnCount()));
            // holder.deckRev.setText(String.valueOf(node.getRevCount()+node.getLrnCount()));
            holder.deckNew.setText(String.valueOf(node.getNewCount() + node.getRevCount() + node.getLrnCount()));
            String ids = Stats.deckLimit(node.getDid(), mCol);
            holder.deckRev.setText(String.valueOf(mCol.cardCount(ids)));
        }
        // Store deck ID in layout's tag for easy retrieval in our click listeners
        holder.deckLayout.setTag(node.getDid());
        holder.countsLayout.setTag(node.getDid());
        holder.endIcon.setTag(node.getDid());
        // holder.endLayout.setTag(node.getDid());
        // Set click listeners
        holder.deckLayout.setOnClickListener(mDeckClickListener);
        holder.deckLayout.setOnLongClickListener(mDeckLongClickListener);
        holder.countsLayout.setOnClickListener(mCountsClickListener);
        holder.endIcon.setOnClickListener(mCountsClickListener);
    // holder.endLayout.setOnClickListener(mCountsClickListener);
    } else if (mCurrentDeck != null) {
        if (tempHolder instanceof CardsListAdapter.CardsViewHolder) {
            CardsListAdapter.CardsViewHolder holder = (CardsListAdapter.CardsViewHolder) tempHolder;
            CardBrowser.CardCache card = mCards.get(position - mDeckList.size() - 1 - 1);
            Timber.i("refresh card:%s", card.getId());
            String question = card.getColumnHeaderText(CardBrowser.Column.SFLD);
            if (card.getColumnHeaderText(CardBrowser.Column.SUSPENDED).equals("True")) {
                holder.deckQuestion.setTextColor(ContextCompat.getColor(mContext, R.color.new_primary_text_third_color));
            // holder.deckAnswer.setTextColor(ContextCompat.getColor(mContext, R.color.new_primary_text_third_color));
            }
            String firstColumnStr = question.isEmpty() ? card.getColumnHeaderText(CardBrowser.Column.MEDIA_NAME) : card.getColumnHeaderText(CardBrowser.Column.SFLD);
            Pattern pattern = Pattern.compile("(?<=≯#).*?(?=#≮)");
            Matcher matcher = pattern.matcher(firstColumnStr);
            String val = "";
            if (matcher.find()) {
                val = matcher.group(0);
                try {
                    String key = mModelKeys.getString(String.valueOf(card.getCard().model().getLong("id")));
                    Timber.i("match key:%s", key);
                    holder.deckQuestion.setText(HtmlUtils.delHTMLTag(firstColumnStr.substring(0, firstColumnStr.indexOf("≯#")) + AESUtil.decrypt(val, key) + firstColumnStr.substring(firstColumnStr.indexOf("#≮") + 2)));
                // holder.deckQuestion.setText(firstColumnStr.substring(0, firstColumnStr.indexOf("≯#")) + aesUtil.getDecryptedMessage(val) + firstColumnStr.substring(firstColumnStr.indexOf("#≮") + 2));
                } catch (Exception e) {
                    e.printStackTrace();
                    holder.deckQuestion.setText(firstColumnStr);
                }
            } else {
                holder.deckQuestion.setText(firstColumnStr);
            }
            // holder.deckAnswer.setText(card.getColumnHeaderText(CardBrowser.Column.ANSWER));
            holder.reviewCount.setText(card.getColumnHeaderText(CardBrowser.Column.REVIEWS));
            holder.forgetCount.setText(card.getColumnHeaderText(CardBrowser.Column.LAPSES));
            holder.due.setText(card.getColumnHeaderText(CardBrowser.Column.DUE2));
            holder.mark.setTag(card.getId());
            holder.flag.setTag(card.getId());
            holder.itemRoot.setTag(card.getId());
            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) holder.itemRoot.getLayoutParams();
            layoutParams.rightMargin = 0;
            holder.itemRoot.setLayoutParams(layoutParams);
            if (card.getCard().note().hasTag("marked")) {
                holder.mark.setImageResource(R.mipmap.mark_star_normal);
            } else {
                holder.mark.setImageResource(R.mipmap.note_star_unselected);
            }
            if (getFlagRes(card.getCard()) != -1) {
                holder.flag.setImageResource(getFlagRes(card.getCard()));
            } else {
                holder.flag.setImageResource(R.mipmap.note_flag_unselected);
            }
            holder.mark.setOnClickListener(v -> {
                CollectionTask.launchCollectionTask(DISMISS_MULTI, markCardHandler(), new TaskData(new Object[] { new long[] { (long) v.getTag() }, Collection.DismissType.MARK_NOTE_MULTI }));
                notifyDataSetChanged();
            });
            holder.flag.setOnClickListener(v -> {
                if (mListPop == null) {
                    mListPop = new ListPopupWindow(mContext);
                    for (int i = 0; i < mFlagRes.length; i++) {
                        Map<String, Object> map = new HashMap<>();
                        map.put("img", mFlagRes[i]);
                        map.put("content", mFlagContent[i]);
                        mFlagList.add(map);
                    }
                    mListPop.setAdapter(new SimpleAdapter(mContext, mFlagList, R.layout.item_flags_list, new String[] { "img", "content" }, new int[] { R.id.flag_icon, R.id.flag_text }));
                    mListPop.setWidth(v.getRootView().getWidth() / 2);
                    mListPop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
                    // 设置是否是模式
                    mListPop.setModal(true);
                }
                mListPop.setOnItemClickListener((parent, view, position1, id) -> {
                    CollectionTask.launchCollectionTask(DISMISS_MULTI, flagCardHandler(), new TaskData(new Object[] { new long[] { (long) v.getTag() }, Collection.DismissType.FLAG, position1 }));
                    notifyDataSetChanged();
                    mListPop.dismiss();
                });
                mListPop.setAnchorView(v);
                mListPop.show();
            });
            holder.itemRoot.setOnClickListener(v -> {
                Intent previewer = new Intent(mContext, Previewer.class);
                long[] ids = getAllCardIds();
                long targetId = (long) v.getTag();
                // }
                for (int i = 0; i < ids.length; i++) {
                    if (ids[i] == targetId) {
                        previewer.putExtra("index", i);
                        break;
                    }
                }
                previewer.putExtra("cardList", ids);
                mContext.startActivityForResultWithoutAnimation(previewer, PREVIEW_CARDS);
            });
        // holder.itemRoot.setOnLongClickListener(mDeckLongClickListener);
        } else if (tempHolder instanceof BrowserTabViewHolder) {
            BrowserTabViewHolder holder = (BrowserTabViewHolder) tempHolder;
            String[] tabArray = mContext.getResources().getStringArray(R.array.deck_info_browser_tab);
            holder.cardsCount.setText(String.format("筛选出%d张卡片", mCards.size()));
            // CardsListAdapter  mCardsAdapter = new CardsListAdapter(mContext.getLayoutInflater(), mContext, new CardsListAdapter.CardListAdapterCallback() {
            // @Override
            // public List<CardBrowser.CardCache> getCards() {
            // if (mCards == null) {
            // mCards = new ArrayList<>();
            // }
            // return mCards;
            // }
            // 
            // 
            // @Override
            // public void onChangeMultiMode(boolean isMultiMode) {
            // }
            // 
            // 
            // @Override
            // public void onItemSelect(int count) {
            // }
            // });
            // mCardsAdapter.setStudyCountLayoutRes(R.layout.item_option_study_count);
            // mCardsAdapter.setDeckClickListener(view -> {
            // Intent previewer = new Intent(mContext, Previewer.class);
            // long[] ids =  getAllCardIds();
            // long targetId = (long) view.getTag();
            // if (ids.length > 100) {
            // //为提高效率 直接复制卡牌
            // long[] finalIds = new long[ids.length + 1];
            // finalIds[0] = targetId;
            // System.arraycopy(ids, 0, finalIds, 1, ids.length);
            // previewer.putExtra("cardList", finalIds);
            // } else {
            // for (int i = 0; i < ids.length; i++) {
            // if (ids[i] == targetId) {
            // ids[i] = ids[0];
            // ids[0] = targetId;
            // }
            // }
            // previewer.putExtra("cardList", ids);
            // }
            // previewer.putExtra("index", 0);
            // mContext.startActivityForResultWithoutAnimation(previewer, PREVIEW_CARDS);
            // });
            // holder.mList .setAdapter(mCardsAdapter);
            // holder.mList.setRecycledViewPool(new RecyclerView.RecycledViewPool());
            // holder.mList.setNestedScrollingEnabled(false);
            // holder.mList.setHasFixedSize(true);
            // holder.mList.setLayoutManager(new LinearLayoutManager(mContext));
            holder.mMore.setTag(SelfStudyActivity.TAB_MAIN_STATE);
            holder.mFixBottom.setVisibility(mDeckList.isEmpty() ? View.GONE : View.VISIBLE);
            holder.mMore.setOnClickListener(mSelfStudyClickListener);
            holder.mTabLayout.removeAllTabs();
            LinearLayout linearLayout = (LinearLayout) holder.mTabLayout.getChildAt(0);
            linearLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
            linearLayout.setDividerDrawable(ContextCompat.getDrawable(mContext, // 设置分割线的样式
            R.drawable.divider_vertical));
            // 设置分割线间隔
            linearLayout.setDividerPadding((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 18, mContext.getResources().getDisplayMetrics()));
            for (int i = 0; i < tabArray.length; i++) {
                TabLayout.Tab tab = holder.mTabLayout.newTab();
                View view = mContext.getLayoutInflater().inflate(R.layout.item_option_tab, null);
                ((TextView) view.findViewById(R.id.name)).setText(tabArray[i]);
                tab.setCustomView(view);
                view.setTag(i);
                int finalI = i;
                view.setOnClickListener(v -> {
                    if (mContext.colIsOpen()) {
                        mCurrentSelectedTab = finalI;
                        holder.mTabLayout.selectTab(holder.mTabLayout.getTabAt(finalI));
                        // estimate maximum number of cards that could be visible (assuming worst-case minimum row height of 20dp)
                        int numCardsToRender = (int) Math.ceil(holder.mList.getHeight() / TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, mContext.getResources().getDisplayMetrics())) + 5;
                        Timber.i("I wanna get %d cards", numCardsToRender);
                        // Perform database query to get all card ids
                        mSearchCardsHandler = new SearchCardsHandler();
                        String searchText = getRestrictByTab(finalI) + "deck:\"" + mCurrentDeck.getString("name") + "\" ";
                        CollectionTask.launchCollectionTask(SEARCH_CARDS, mSearchCardsHandler, new TaskData(new Object[] { searchText, true, numCardsToRender, 0, 0 }));
                    }
                });
                holder.mTabLayout.addTab(tab);
            }
            holder.mTabLayout.selectTab(holder.mTabLayout.getTabAt(mCurrentSelectedTab));
            if (!mInitBrowserCards) {
                mInitBrowserCards = true;
                holder.mTabLayout.getTabAt(0).getCustomView().performClick();
            }
        }
    }
}
Also used : ImageButton(android.widget.ImageButton) LinearLayout(android.widget.LinearLayout) Arrays(java.util.Arrays) Deck(com.ichi2.libanki.Deck) ProgressBar(android.widget.ProgressBar) NonNull(androidx.annotation.NonNull) WindowManager(android.view.WindowManager) ImageView(android.widget.ImageView) ColorDrawable(android.graphics.drawable.ColorDrawable) LinkMovementMethod(android.text.method.LinkMovementMethod) Drawable(android.graphics.drawable.Drawable) SelfStudyActivity(com.ichi2.anki.SelfStudyActivity) Decks(com.ichi2.libanki.Decks) Matcher(java.util.regex.Matcher) Map(java.util.Map) Previewer(com.ichi2.anki.Previewer) View(android.view.View) Button(android.widget.Button) TaskData(com.ichi2.async.TaskData) RecyclerView(androidx.recyclerview.widget.RecyclerView) StudySettingActivity(com.ichi2.anki.StudySettingActivity) ContextCompat(androidx.core.content.ContextCompat) CardView(androidx.cardview.widget.CardView) DeckPicker(com.ichi2.anki.DeckPicker) HtmlUtils(com.ichi2.utils.HtmlUtils) TabLayout(com.google.android.material.tabs.TabLayout) CardUtils(com.ichi2.anki.CardUtils) SEARCH_CARDS(com.ichi2.async.CollectionTask.TASK_TYPE.SEARCH_CARDS) Set(java.util.Set) JSONObject(com.ichi2.utils.JSONObject) CardBrowser(com.ichi2.anki.CardBrowser) Timber(timber.log.Timber) ViewGroup(android.view.ViewGroup) CollectionHelper(com.ichi2.anki.CollectionHelper) AnkiActivity(com.ichi2.anki.AnkiActivity) List(java.util.List) Nullable(androidx.annotation.Nullable) TextView(android.widget.TextView) SimpleAdapter(android.widget.SimpleAdapter) AnkiDroidApp(com.ichi2.anki.AnkiDroidApp) Consts(com.ichi2.libanki.Consts) CompatHelper(com.ichi2.compat.CompatHelper) RelativeLayout(android.widget.RelativeLayout) DECK_OPTIONS(com.ichi2.anki.AbstractFlashcardViewer.DECK_OPTIONS) TaskListenerWithContext(com.ichi2.async.TaskListenerWithContext) LinearLayoutManager(androidx.recyclerview.widget.LinearLayoutManager) Pattern(java.util.regex.Pattern) Window(android.view.Window) WebViewActivity(com.ichi2.anki.WebViewActivity) TaskListener(com.ichi2.async.TaskListener) Spanned(android.text.Spanned) CornerTransform(com.ichi2.utils.CornerTransform) R(com.ichi2.anki.R) Dialog(android.app.Dialog) Intent(android.content.Intent) HashMap(java.util.HashMap) DISMISS_MULTI(com.ichi2.async.CollectionTask.TASK_TYPE.DISMISS_MULTI) Collection(com.ichi2.libanki.Collection) TypedArray(android.content.res.TypedArray) ArrayList(java.util.ArrayList) CardsListAdapter.getFlagRes(com.ichi2.anki.widgets.CardsListAdapter.getFlagRes) DiskCacheStrategy(com.bumptech.glide.load.engine.DiskCacheStrategy) Utils(com.ichi2.libanki.Utils) ListPopupWindow(androidx.appcompat.widget.ListPopupWindow) RequestOptions(com.bumptech.glide.request.RequestOptions) AbstractDeckTreeNode(com.ichi2.libanki.sched.AbstractDeckTreeNode) Stats(com.ichi2.libanki.stats.Stats) LayoutInflater(android.view.LayoutInflater) CollectionTask(com.ichi2.async.CollectionTask) SelfStudyActivity.getPositionMap(com.ichi2.anki.SelfStudyActivity.getPositionMap) Color(android.graphics.Color) Gravity(android.view.Gravity) AESUtil(com.ichi2.utils.AESUtil) Glide(com.bumptech.glide.Glide) SharedPreferences(android.content.SharedPreferences) TypedValue(android.util.TypedValue) TreeMap(java.util.TreeMap) AdaptionUtil(com.ichi2.utils.AdaptionUtil) PREVIEW_CARDS(com.ichi2.anki.SelfStudyActivity.PREVIEW_CARDS) Card(com.ichi2.libanki.Card) KEY_STRUCT_INIT(com.ichi2.anki.StudyOptionsFragment.KEY_STRUCT_INIT) VisibleForTesting(androidx.annotation.VisibleForTesting) ActivityTransitionAnimation(com.ichi2.anim.ActivityTransitionAnimation) RequestOptions(com.bumptech.glide.request.RequestOptions) Matcher(java.util.regex.Matcher) HashMap(java.util.HashMap) CardBrowser(com.ichi2.anki.CardBrowser) WindowManager(android.view.WindowManager) TaskData(com.ichi2.async.TaskData) CornerTransform(com.ichi2.utils.CornerTransform) ListPopupWindow(androidx.appcompat.widget.ListPopupWindow) Dialog(android.app.Dialog) AbstractDeckTreeNode(com.ichi2.libanki.sched.AbstractDeckTreeNode) Window(android.view.Window) ListPopupWindow(androidx.appcompat.widget.ListPopupWindow) Pattern(java.util.regex.Pattern) SimpleAdapter(android.widget.SimpleAdapter) Intent(android.content.Intent) ImageView(android.widget.ImageView) View(android.view.View) RecyclerView(androidx.recyclerview.widget.RecyclerView) CardView(androidx.cardview.widget.CardView) TextView(android.widget.TextView) ColorDrawable(android.graphics.drawable.ColorDrawable) RelativeLayout(android.widget.RelativeLayout) JSONObject(com.ichi2.utils.JSONObject) LinearLayout(android.widget.LinearLayout)

Example 33 with Deck

use of com.ichi2.libanki.Deck in project AnkiChinaAndroid by ankichinateam.

the class DeckAdapter method onBindViewHolder.

@Override
public void onBindViewHolder(RecyclerView.ViewHolder tempHolder, int position) {
    // Update views for this node
    if (tempHolder instanceof HeaderViewHolder) {
        HeaderViewHolder holder = (HeaderViewHolder) tempHolder;
        holder.cost_time.setText(mCost == null || mCost.isEmpty() ? "0" : mCost);
        holder.new_card_num.setText(mNewCard == null || mNewCard.isEmpty() ? "0" : mNewCard);
        holder.review_card_num.setText(mNeedReviewCard == null || mNeedReviewCard.isEmpty() ? "0" : mNeedReviewCard);
        holder.tv_resource.setOnClickListener(mMarketClickListener);
        if (mAdText != null && !mAdText.isEmpty()) {
            holder.main_ad_layout.setVisibility(View.VISIBLE);
            holder.main_ad_text.setText(mAdText);
            holder.main_ad_layout.setOnClickListener(mAdClickListener);
            holder.remove_ad.setOnClickListener(v -> {
                holder.main_ad_layout.setVisibility(View.GONE);
            // LinearLayout.LayoutParams params= (LinearLayout.LayoutParams) holder.today_title.getLayoutParams();
            // params.topMargin= AdaptionUtil.dip2px(mContext, 9);
            });
        } else {
            holder.main_ad_layout.setVisibility(View.GONE);
        }
    } else if (tempHolder instanceof EmptyViewHolder) {
        EmptyViewHolder holder = (EmptyViewHolder) tempHolder;
        holder.btn_get_card.setOnClickListener(mMarketClickListener);
    } else if (tempHolder instanceof DeckAdapter.ViewHolder) {
        position--;
        DeckAdapter.ViewHolder holder = (ViewHolder) tempHolder;
        AbstractDeckTreeNode node = mDeckList.get(position);
        // Set the expander icon and padding according to whether or not there are any subdecks
        // RelativeLayout deckLayout = holder.deckLayout;
        // int rightPadding = (int) deckLayout.getResources().getDimension(R.dimen.deck_picker_right_padding);
        // Timber.d("onBindViewHolder,mHasSubdecks:" + mHasSubdecks);
        // if (mHasSubdecks) {
        // int smallPadding = (int) deckLayout.getResources().getDimension(R.dimen.deck_picker_left_padding_small);
        // deckLayout.setPadding(smallPadding, 0, rightPadding, 0);
        // holder.deckExpander.setVisibility(View.VISIBLE);
        // holder.fileBag.setVisibility(View.VISIBLE);
        // // Create the correct expander for this deck
        // 
        // setDeckExpander(holder.deckExpander,holder.fileBag,holder.indentView, node);
        // } else {
        // holder.deckExpander.setVisibility(View.GONE);
        // holder.fileBag.setVisibility(View.GONE);
        // int normalPadding = (int) deckLayout.getResources().getDimension(R.dimen.deck_picker_left_padding);
        // deckLayout.setPadding(normalPadding, 0, rightPadding, 0);
        // }
        // holder.fileBag.setOnClickListener(v -> holder.deckExpander.performClick());
        // holder.filebagLayout.setOnClickListener(v -> holder.deckExpander.performClick());
        // if (node.hasChildren()) {
        // holder.deckExpander.setTag(node.getDid());
        // holder.deckExpander.setOnClickListener(mDeckExpanderClickListener);
        // } else {
        // holder.deckExpander.setOnClickListener(null);
        // }
        // holder.deckLayout.setBackgroundResource(mRowCurrentDrawable);
        // Set background colour. The current deck has its own color
        // if (isCurrentlySelectedDeck(node)) {
        // holder.deckLayout.setBackgroundResource(mRowCurrentDrawable);
        // if (mPartiallyTransparentForBackground) {
        // setBackgroundAlpha(holder.deckLayout, SELECTED_DECK_ALPHA_AGAINST_BACKGROUND);
        // }
        // } else {
        // CompatHelper.getCompat().setSelectableBackground(holder.deckLayout);
        // }
        // Set deck name and colour. Filtered decks have their own colour
        holder.deckName.setText(node.getLastDeckNameComponent());
        if (mCol.getDecks().isDyn(node.getDid())) {
            holder.deckName.setTextColor(mDeckNameDynColor);
        } else {
            holder.deckName.setTextColor(mDeckNameDefaultColor);
        }
        double[] data;
        // Set the card counts and their colors
        if (node.shouldDisplayCounts()) {
            holder.deckNew.setText(String.valueOf(node.getNewCount()));
            // holder.deckNew.setTextColor((node.getNewCount() == 0) ? mZeroCountColor : mNewCountColor);
            holder.deckLearn.setText(String.valueOf(node.getLrnCount()));
            // holder.deckLearn.setTextColor((node.getLrnCount() == 0) ? mZeroCountColor : mLearnCountColor);
            holder.deckRev.setText(String.valueOf(node.getRevCount() + node.getLrnCount()));
            // holder.deckRev.setTextColor((node.getRevCount() == 0) ? mZeroCountColor : mReviewCountColor);
            data = node.getStudyData();
        } else {
            data = new double[] { 0.0, 0.0, 0.0 };
        }
        // Store deck ID in layout's tag for easy retrieval in our click listeners
        holder.deckLayout.setTag(node.getDid());
        holder.countsLayout.setTag(node.getDid());
        // double[] data = calculateStat(mCol, node.getDid());
        double percent = 0;
        if (data[2] == 0) {
            // 新卡已学完,显示已掌握
            percent = (data[0] + data[1] + data[2] <= 0) ? 0 : (data[0] / (data[0] + data[1] + data[2]) * 100);
            holder.handled_num.setText(String.format(Locale.CHINA, "%.0f/%.0f", data[0], (data[0] + data[1] + data[2])));
            holder.handled_percent.setText((String.format(Locale.CHINA, "已掌握 %.1f", percent)) + "%");
        } else {
            percent = (data[0] + data[1] + data[2] <= 0) ? 0 : ((data[0] + data[1]) / (data[0] + data[1] + data[2]) * 100);
            holder.handled_num.setText(String.format(Locale.CHINA, "%.0f/%.0f", data[0] + data[1], (data[0] + data[1] + data[2])));
            holder.handled_percent.setText((String.format(Locale.CHINA, "已学 %.1f", percent)) + "%");
        }
        holder.studyProgress.setMax(100 * 100);
        holder.studyProgress.setProgress((int) (percent * 100));
        // Set click listeners
        holder.deckLayout.setOnClickListener(mDeckClickListener);
        holder.deckLayout.setOnLongClickListener(mDeckLongClickListener);
        holder.countsLayout.setOnClickListener(mCountsClickListener);
    }
}
Also used : AbstractDeckTreeNode(com.ichi2.libanki.sched.AbstractDeckTreeNode)

Example 34 with Deck

use of com.ichi2.libanki.Deck in project AnkiChinaAndroid by ankichinateam.

the class DeckInfoListAdapter method processNames.

private void processNames() {
    Deck deck = mCurrentDeck;
    long id = deck.optLong("id");
    Timber.i("processNames:当前节点:%s", deck.optString("name"));
    for (Deck parent : mCol.getDecks().parents(id)) {
        Timber.d("my parents names:%s", parent.optString("name"));
        if (!parent.optString("name").contains("::")) {
            // 祖先节点
            long ancestorID = parent.optLong("id");
            mCurrentIDs.add(ancestorID);
            TreeMap<String, Long> map = mCol.getDecks().children(ancestorID);
            Set<String> keySet = map.keySet();
            for (String str : keySet) {
                // Timber.d("find my id :%s,%s", str, map.get(str));
                // if(str.split("::").length!=deck.optString("name").split("::").length)
                mCurrentIDs.add(map.get(str));
            }
        }
    }
    // 
    if (mCurrentIDs.isEmpty()) {
        mCurrentIDs.add(id);
        TreeMap<String, Long> map = mCol.getDecks().children(id);
        Set<String> keySet = map.keySet();
        for (String str : keySet) {
            // Timber.d("find my child id :%s,%s", str, map.get(str));
            mCurrentIDs.add(map.get(str));
        }
    }
    // mCurrentIDs.addAll(mCol.getDecks().childDids(id, mCol.getDecks().childMap()));
    TreeMap<String, Long> map = mCol.getDecks().children(id);
    Set<String> keySet = map.keySet();
    for (String str : keySet) {
        if (Decks.path(str).length > Decks.path(deck.optString("name")).length + 1) {
            mHasSubdecks = true;
        }
    }
    for (Long findID : mCurrentIDs) {
        Timber.d("find my id :%s", mCol.getDecks().get(findID).optString("name"));
    }
// }
// mIniCollapsedStatus=true;
}
Also used : Deck(com.ichi2.libanki.Deck)

Example 35 with Deck

use of com.ichi2.libanki.Deck in project AnkiChinaAndroid by ankichinateam.

the class ReminderService method onReceive.

@Override
public void onReceive(Context context, Intent intent) {
    cancelDeckReminder(context, intent);
    // 0 is not a valid dconf id.
    final long dConfId = intent.getLongExtra(EXTRA_DECK_OPTION_ID, 0);
    if (dConfId == 0) {
        Timber.w("onReceive - dConfId 0, returning");
        return;
    }
    CollectionHelper colHelper;
    Collection col;
    try {
        colHelper = CollectionHelper.getInstance();
        col = colHelper.getCol(context);
    } catch (Throwable t) {
        Timber.w("onReceive - unexpectedly unable to get collection. Returning.");
        return;
    }
    if (null == col || !colHelper.colIsOpen()) {
        Timber.w("onReceive - null or closed collection, unable to process reminders");
        return;
    }
    if (col.getDecks().getConf(dConfId) == null) {
        final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        final PendingIntent reminderIntent = PendingIntent.getBroadcast(context, (int) dConfId, new Intent(context, ReminderService.class).putExtra(EXTRA_DECK_OPTION_ID, dConfId), 0);
        alarmManager.cancel(reminderIntent);
    }
    final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
    if (!notificationManager.areNotificationsEnabled()) {
        Timber.v("onReceive - notifications disabled, returning");
        return;
    }
    List<DeckDueTreeNode> decksDue = getDeckOptionDue(col, dConfId, true);
    if (null == decksDue) {
        Timber.v("onReceive - no decks due, returning");
        return;
    }
    for (DeckDueTreeNode deckDue : decksDue) {
        long deckId = deckDue.getDid();
        final int total = deckDue.getRevCount() + deckDue.getLrnCount() + deckDue.getNewCount();
        if (total <= 0) {
            Timber.v("onReceive - no cards due in deck %d", deckId);
            continue;
        }
        Timber.v("onReceive - deck '%s' due count %d", deckDue.getFullDeckName(), total);
        final Notification notification = new NotificationCompat.Builder(context, NotificationChannels.getId(NotificationChannels.Channel.DECK_REMINDERS)).setCategory(NotificationCompat.CATEGORY_REMINDER).setContentTitle(context.getString(R.string.reminder_title)).setContentText(context.getResources().getQuantityString(R.plurals.reminder_text, total, deckDue.getFullDeckName(), total)).setSmallIcon(R.drawable.ic_stat_notify).setColor(ContextCompat.getColor(context, R.color.material_light_blue_700)).setContentIntent(PendingIntent.getActivity(context, (int) deckId, getReviewDeckIntent(context, deckId), PendingIntent.FLAG_UPDATE_CURRENT)).setAutoCancel(true).build();
        notificationManager.notify((int) deckId, notification);
        Timber.v("onReceive - notification state: %s", notification);
    }
}
Also used : NotificationManagerCompat(androidx.core.app.NotificationManagerCompat) Intent(android.content.Intent) PendingIntent(android.app.PendingIntent) Notification(android.app.Notification) DeckDueTreeNode(com.ichi2.libanki.sched.DeckDueTreeNode) Collection(com.ichi2.libanki.Collection) AlarmManager(android.app.AlarmManager) CollectionHelper(com.ichi2.anki.CollectionHelper) PendingIntent(android.app.PendingIntent)

Aggregations

Deck (com.ichi2.libanki.Deck)100 Collection (com.ichi2.libanki.Collection)97 JSONObject (com.ichi2.utils.JSONObject)88 Test (org.junit.Test)80 JSONArray (com.ichi2.utils.JSONArray)55 Card (com.ichi2.libanki.Card)53 Note (com.ichi2.libanki.Note)50 ArrayList (java.util.ArrayList)47 RobolectricTest (com.ichi2.anki.RobolectricTest)44 DeckConfig (com.ichi2.libanki.DeckConfig)37 JSONException (com.ichi2.utils.JSONException)34 NonNull (androidx.annotation.NonNull)30 HashMap (java.util.HashMap)29 Model (com.ichi2.libanki.Model)23 Map (java.util.Map)22 Intent (android.content.Intent)21 Resources (android.content.res.Resources)18 TextView (android.widget.TextView)18 SharedPreferences (android.content.SharedPreferences)17 Cursor (android.database.Cursor)17