package com.qubling.sidekick.ui.module; import java.util.Collections; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Parcelable; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; import android.webkit.WebViewClient; import com.qubling.sidekick.R; import com.qubling.sidekick.fetch.Fetcher; import com.qubling.sidekick.fetch.UpdateFetcher; import com.qubling.sidekick.fetch.cpan.CPANFetcher; import com.qubling.sidekick.instance.Module; import com.qubling.sidekick.model.ModuleModel; import com.qubling.sidekick.search.ResultSet; import com.qubling.sidekick.search.Schema; import com.qubling.sidekick.search.Search; import com.qubling.sidekick.util.LinkedListStack; import com.qubling.sidekick.util.Stack; import com.qubling.sidekick.widget.ModuleHelper; public class ModuleViewFragment extends ModuleFragment implements ModuleViewThingyFragment, Fetcher.OnFinished<Module> { private Stack<Module> moduleHistory = new LinkedListStack<Module>(); private Schema searchSession; private Module module; public void setModule(Module module) { // Log.d("ModuleViewFragment", "setModule(): " + new Gson().toJson(module)); // If we have a module in place, push it on to the history stack if (this.module != null) { moduleHistory.push(module); } this.module = module; this.module.attachToModel(searchSession.getModuleModel()); View moduleInfo = getActivity().findViewById(R.id.module_info); ModuleHelper.updateItem(moduleInfo, module); } public Module getModule() { return module; } @Override public void onCreate(Bundle state) { super.onCreate(state); searchSession = new Schema(this.getActivity()); } public void setModuleViaWebView(String url, String baseUrl) { moduleHistory.push(module); String moduleName = url.substring(baseUrl.length()); module = searchSession.getModuleModel().acquireInstance(moduleName); fetchModule(); } @Override public void onActivityCreated(Bundle state) { super.onActivityCreated(state); WebView podView = (WebView) getActivity().findViewById(R.id.module_pod); podView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView podView, String url) { // Log.d("ModuleViewActivity", "URL: " + url); // Let the built-in handler get all the internal URLs if (url.startsWith("file:///android_asset/web/")) { return false; } // Let the built-in handler get all the POD API URLs else if (url.startsWith(CPANFetcher.METACPAN_API_POD_URL)) { return false; } // Rewrite MetaCPAN module URLs to fetch the POD else if (url.startsWith(CPANFetcher.METACPAN_MODULE_URL)) { setModuleViaWebView(url, CPANFetcher.METACPAN_MODULE_URL); return true; } // Rewrite MetaCPAN secure module URLs to fetch the POD else if (url.startsWith(CPANFetcher.METACPAN_SECURE_MODULE_URL)) { setModuleViaWebView(url, CPANFetcher.METACPAN_SECURE_MODULE_URL); return true; } // For anything else, load the browser else { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); startActivity(intent); return true; } } }); if (state != null && state.containsKey("viewModule")) { module = (Module) state.getParcelable("viewModule"); module.attachToModel(searchSession.getModuleModel()); } if (state != null && state.containsKey("viewModuleHistory")) { Parcelable[] historyArray = state.getParcelableArray("viewModuleHistory"); Module[] moduleHistoryArray = new Module[historyArray.length]; System.arraycopy(historyArray, 0, moduleHistoryArray, 0, historyArray.length); moduleHistory = new LinkedListStack<Module>(); Collections.addAll(moduleHistory, moduleHistoryArray); } fetchModule(); View moduleInfo = getActivity().findViewById(R.id.module_info); moduleInfo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getModuleActivity().onReleaseClick(module); } }); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.module_view_fragment, container, false); } @Override public void onSaveInstanceState(Bundle state) { super.onSaveInstanceState(state); Parcelable[] historyArray = new Parcelable[moduleHistory.size()]; moduleHistory.toArray(historyArray); state.putParcelableArray("viewModuleHistory", historyArray); state.putParcelable("viewModule", module); } public Search<Module> buildSearch() { ModuleModel modules = searchSession.getModuleModel(); Fetcher<Module> moduleFetch = modules.fetch(); moduleFetch.getResultSet().add(module); UpdateFetcher<Module> fetchPod = modules.fetchPod(); // TODO These are common with ModuleSearchFragment, SHARE!!! UpdateFetcher<Module> fetchFavorites = modules.fetchReleaseFavorites(""); UpdateFetcher<Module> fetchRatings = modules.fetchReleaseRatings(); UpdateFetcher<Module> fetchAuthors = modules.fetchAuthors(); UpdateFetcher<Module> fetchGravatars = modules.fetchGravatars(GRAVATAR_DP_SIZE); @SuppressWarnings("unchecked") Search<Module> search = searchSession.doFetch(moduleFetch, this) .thenDoFetch( fetchPod, fetchFavorites, fetchRatings, fetchAuthors .thenDoFetch(fetchGravatars) ); search.addOnSearchActivityListener(this.getModuleActivity()); return search; } public void fetchModule() { // No module loaded, skip it if (module == null) return; Search<Module> search = buildSearch(); search.start(); } public void onFinishedFetch(Fetcher<Module> fetcher, ResultSet<Module> modules) { // Don't do anything if we don't have an activity (i.e., don't NPE either) if (getActivity() == null) return; // Check to see if the module fetched can be shown here if (getModuleActivity().isModuleAcceptableForThisActivity(module)) { View moduleInfo = getActivity().findViewById(R.id.module_info); ModuleHelper.updateItem(moduleInfo, module); if (module.getRawPod() != null) { WebView podView = (WebView) getActivity().findViewById(R.id.module_pod); // Avoid an NPE here, just in case if (podView == null) return; String formattedPod = "<html><head><link href=\"style/pod.css\" type=\"text/css\" rel=\"stylesheet\"/></head><body class=\"pod\">" + module.getRawPod() + "</body></html>"; podView.loadDataWithBaseURL("file:///android_asset/web/pod/", formattedPod, "text/html", "UTF-8", null); } } // The activity doesn't want to show this activity and has initiated a new one else { module = moduleHistory.pop(); } } public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && !moduleHistory.isEmpty()) { module = moduleHistory.pop(); View moduleInfo = getActivity().findViewById(R.id.module_info); ModuleHelper.updateItem(moduleInfo, module); fetchModule(); return true; } return false; } }