<commit_before>/*
 * Copyright (c) 2019 toastkidjp.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompany this distribution.
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html.
 */
package jp.toastkid.yobidashi.search.trend

import androidx.core.view.isVisible
import com.google.android.flexbox.AlignItems
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexWrap
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.flexbox.JustifyContent
import jp.toastkid.lib.preference.PreferenceApplier
import jp.toastkid.yobidashi.databinding.ModuleSearchHourlyTrendBinding
import jp.toastkid.yobidashi.search.SearchFragmentViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * @author toastkidjp
 */
class HourlyTrendModule(
        private val hourlyTrendModule: ModuleSearchHourlyTrendBinding?,
        viewModel: SearchFragmentViewModel
) {

    private val trendApi = TrendApi()

    private var adapter: Adapter? = null

    private var lastJob: Job = Job()

    private var enable: Boolean

    init {
        val context = hourlyTrendModule?.root?.context
        enable = if (context == null) false else PreferenceApplier(context).isEnableTrendModule()

        adapter = Adapter(viewModel)
        hourlyTrendModule?.trendItems?.adapter = adapter
        val layoutManager = FlexboxLayoutManager(hourlyTrendModule?.root?.context)
        layoutManager.flexDirection = FlexDirection.ROW
        layoutManager.flexWrap = FlexWrap.WRAP
        layoutManager.justifyContent = JustifyContent.FLEX_START
        layoutManager.alignItems = AlignItems.STRETCH
        hourlyTrendModule?.trendItems?.layoutManager = layoutManager
    }

    fun request() {
        lastJob.cancel()
        if (!enable) {
            return
        }

        lastJob = CoroutineScope(Dispatchers.Main).launch {
            withContext(Dispatchers.IO) {
                adapter?.replace(trendApi()?.take(10))
            }
            hourlyTrendModule?.root?.isVisible = adapter?.isNotEmpty() ?: false
            adapter?.notifyDataSetChanged()
        }
    }

    fun setEnable(newState: Boolean) {
        this.enable = newState

        hourlyTrendModule?.root?.isVisible = newState
    }

    fun dispose() {
        lastJob.cancel()
    }
}<commit_msg>bugfix #412 Surround try-catch for avoiding crash on disconnect from network.<commit_after>/*
 * Copyright (c) 2019 toastkidjp.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompany this distribution.
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html.
 */
package jp.toastkid.yobidashi.search.trend

import androidx.core.view.isVisible
import com.google.android.flexbox.AlignItems
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexWrap
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.flexbox.JustifyContent
import jp.toastkid.lib.preference.PreferenceApplier
import jp.toastkid.yobidashi.databinding.ModuleSearchHourlyTrendBinding
import jp.toastkid.yobidashi.search.SearchFragmentViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.IOException

/**
 * @author toastkidjp
 */
class HourlyTrendModule(
        private val hourlyTrendModule: ModuleSearchHourlyTrendBinding?,
        viewModel: SearchFragmentViewModel
) {

    private val trendApi = TrendApi()

    private var adapter: Adapter? = null

    private var lastJob: Job = Job()

    private var enable: Boolean

    init {
        val context = hourlyTrendModule?.root?.context
        enable = if (context == null) false else PreferenceApplier(context).isEnableTrendModule()

        adapter = Adapter(viewModel)
        hourlyTrendModule?.trendItems?.adapter = adapter
        val layoutManager = FlexboxLayoutManager(hourlyTrendModule?.root?.context)
        layoutManager.flexDirection = FlexDirection.ROW
        layoutManager.flexWrap = FlexWrap.WRAP
        layoutManager.justifyContent = JustifyContent.FLEX_START
        layoutManager.alignItems = AlignItems.STRETCH
        hourlyTrendModule?.trendItems?.layoutManager = layoutManager
    }

    fun request() {
        lastJob.cancel()
        if (!enable) {
            return
        }

        lastJob = CoroutineScope(Dispatchers.Main).launch {
            withContext(Dispatchers.IO) {
                val trendItems = try {
                    trendApi()
                } catch (e: IOException) {
                    Timber.e(e)
                    null
                }
                adapter?.replace(trendItems?.take(10))
            }
            hourlyTrendModule?.root?.isVisible = adapter?.isNotEmpty() ?: false
            adapter?.notifyDataSetChanged()
        }
    }

    fun setEnable(newState: Boolean) {
        this.enable = newState

        hourlyTrendModule?.root?.isVisible = newState
    }

    fun dispose() {
        lastJob.cancel()
    }
}
{'fraction_non_alphanumeric': 0.08376005852231164, 'fraction_numerical': 0.004206291148500366, 'mean_word_length': 3.105855855855856, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '984093', 'n_tokens_mistral': 1618, 'n_tokens_neox': 1531, 'n_words': 319}